从python中的内部类访问外部类

T. *_*one 86 python scope nested inner-classes

我有这样的情况......

class Outer(object):

    def some_method(self):
        # do something

    class Inner(object):
        def __init__(self):
            self.Outer.some_method()    # <-- this is the line in question
Run Code Online (Sandbox Code Playgroud)

如何OuterInner类中访问类的方法?

编辑 - 感谢您的回复.我的结论是,我需要重新评估我是如何设计这个实现的,并提出一个更强大的方法.

Dan*_*llo 57

嵌套类的方法不能直接访问外部类的实例的属性.

请注意,这并不一定,甚至当你创建内部类的实例存在的外部类的一个实例的情况.

实际上,通常建议不要使用嵌套类,因为嵌套并不意味着内部类和外部类之间存在任何特定关系.

  • 内部类当然确实暗示了与外部类的关系,通常与内部类的隐含使用范围或组织命名空间有关. (13认同)
  • 嗯,Python 比 Java/C++ 更活泼……请参阅下面的答案。如果我们通常是分裂头发,我真的不能告诉你我的“方法中的嵌套类”是否算作内部类。不过,在这一点上,我必须调用鸭子类型:如果它完成了内部类可能做的所有事情......从 Pythonic 的角度来看,可能是时候对分裂的头发感到厌烦了 (2认同)

小智 50

您正在尝试从内部类实例访问Outer的类实例.所以只需使用factory-method构建Inner实例并将Outer实例传递给它.

class Outer(object):

    def createInner(self):
        return Outer.Inner(self)

    class Inner(object):
        def __init__(self, outer_instance):
            self.outer_instance = outer_instance
            self.outer_instance.somemethod()

        def inner_method(self):
            self.outer_instance.anothermethod()
Run Code Online (Sandbox Code Playgroud)


mik*_*ent 24

也许我很生气,但这似乎很容易 - 事情是让你的内部类在外部类的方法中...

def do_sthg( self ):
    ...

def messAround( self ):

    outerClassSelf = self

    class mooble():
        def do_sthg_different( self ):
            ...
            outerClassSelf.do_sthg()
Run Code Online (Sandbox Code Playgroud)

另外......"self"仅按惯例使用,因此您可以这样做:

def do_sthg( self ):
    ...

def messAround( outerClassSelf ):

    class mooble():
        def do_sthg_different( self ):
            ...
            outerClassSelf.do_sthg()
Run Code Online (Sandbox Code Playgroud)

可能有人反对说,你不能从外部类外部创建这个内部类......但事实并非如此:

class Bumblebee():

    def do_sthg( self ):
        print "sthg"

    def giveMeAnInnerClass( outerClassSelf ):

        class mooble():
            def do_sthg_different( self ):
                print "something diff\n"
                outerClassSelf.do_sthg()
        return mooble
Run Code Online (Sandbox Code Playgroud)

然后,在几英里之外:

blob = Bumblebee().giveMeAnInnerClass()()
blob.do_sthg_different()    
Run Code Online (Sandbox Code Playgroud)

甚至将船推出一点并扩展这个内部类(NB以获得super()工作你必须将mooble的类签名改为"class mooble(object)"

class InnerBumblebeeWithAddedBounce( Bumblebee().giveMeAnInnerClass() ):
    def bounce( self ):
        print "bounce"

    def do_sthg_different( self ):
        super( InnerBumblebeeWithAddedBounce, self ).do_sthg_different()
        print "and more different"


ibwab = InnerBumblebeeWithAddedBounce()    
ibwab.bounce()
ibwab.do_sthg_different()
Run Code Online (Sandbox Code Playgroud)

后来

mrh1997提出了一个关于使用这种技术传递的内部类的非公共继承的有趣观点.但似乎解决方案非常简单:

class Fatty():
    def do_sthg( self ):
        pass

    class InnerFatty( object ):
        pass

    def giveMeAnInnerFattyClass(self):
        class ExtendedInnerFatty( Fatty.InnerFatty ):
            pass
        return ExtendedInnerFatty

fatty1 = Fatty()
fatty2 = Fatty()

innerFattyClass1 = fatty1.giveMeAnInnerFattyClass()
innerFattyClass2 = fatty2.giveMeAnInnerFattyClass()

print ( issubclass( innerFattyClass1, Fatty.InnerFatty ))
print ( issubclass( innerFattyClass2, Fatty.InnerFatty ))
Run Code Online (Sandbox Code Playgroud)

  • 我不知道它叫什么……但我可能会建议其他发帖者没有看到这个的原因是因为可能没有完全意识到Python中的大多数东西都是非神圣的,包括“自我” “(任意名称)和类 - 它们是“第一类对象”,这似乎意味着您可以以相当令人震惊的方式操纵它们 (3认同)

esp*_*sp0 10

晚了几年......但是为了扩展@mike rodent的精彩答案,我在下面提供了我自己的示例,展示了他的解决方案是多么灵活,以及为什么它应该(或应该被接受回答。

Python 3.7

class Parent():

    def __init__(self, name):
        self.name = name
        self.children = []

    class Inner(object):
        pass

    def Child(self, name):
        parent = self
        class Child(Parent.Inner):
            def __init__(self, name):
                self.name = name
                self.parent = parent
                parent.children.append(self)
        return Child(name)



parent = Parent('Bar')

child1 = parent.Child('Foo')
child2 = parent.Child('World')

print(
    # Getting its first childs name
    child1.name, # From itself
    parent.children[0].name, # From its parent
    # Also works with the second child
    child2.name,
    parent.children[1].name,
    # Go nuts if you want
    child2.parent.children[0].name,
    child1.parent.children[1].name
)

print(
    # Getting the parents name
    parent.name, # From itself
    child1.parent.name, # From its children
    child2.parent.name,
    # Go nuts again if you want
    parent.children[0].parent.name,
    parent.children[1].parent.name,
    # Or insane
    child2.parent.children[0].parent.children[1].parent.name,
    child1.parent.children[1].parent.children[0].parent.name
)


# Second parent? No problem
parent2 = Parent('John')
child3 = parent2.Child('Doe')
child4 = parent2.Child('Appleseed')

print(
    child3.name, parent2.children[0].name,
    child4.name, parent2.children[1].name,
    parent2.name # ....
)
Run Code Online (Sandbox Code Playgroud)

输出:

Foo Foo World World Foo World
Bar Bar Bar Bar Bar Bar Bar
Doe Doe Appleseed Appleseed John
Run Code Online (Sandbox Code Playgroud)

再次,一个精彩的答案,支持你,迈克!


fly*_*eep 6

我找到了这个

调整以适应您的问题:

class Outer(object):
    def some_method(self):
        # do something

    class _Inner(object):
        def __init__(self, outer):
            outer.some_method()
    def Inner(self):
        return _Inner(self)
Run Code Online (Sandbox Code Playgroud)

我相信你可以以某种方式为这个或其他东西写一个装饰器

相关:python 内部类的目的是什么?