如何从内部类访问外部类?

187 投票
16 回答
164535 浏览
提问于 2025-04-15 17:46

我遇到了这样的情况……

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

我该如何从Inner类访问Outer类的方法呢?

16 个回答

51

也许我有点疯狂,但这看起来确实很简单——关键是要在外部类的方法里面定义你的内部类...

def do_sthg(self):
    ...

def mess_around(self):

    outer_class_self = self

    class Mooble():
        def do_sthg_different(self):
            ...
            outer_class_self.do_sthg()

而且... “self”只是一个约定,所以你可以这样做:

def do_sthg(self):
    ...

def mess_around(outer_class_self):

    class Mooble():
        def do_sthg_different(self):
            ...
            outer_class_self.do_sthg()

有人可能会反对说,这样你就不能在外部类之外创建这个内部类了... 但这并不是真的:

class Bumblebee():

    def do_sthg(self):
        print "sthg"
    
    def give_me_an_inner_class(outer_class_self):

        class Mooble():
            def do_sthg_different(self):
                print "something diff\n"
                outer_class_self.do_sthg()
        return Mooble
    

然后,在很远的地方:

blob = Bumblebee().give_me_an_inner_class()()
blob.do_sthg_different()    

甚至可以大胆一点,扩展这个内部类(注意,要让 super() 正常工作,你需要把 Mooble 的类签名改成 class Mooble(object))。

class InnerBumblebeeWithAddedBounce(Bumblebee().give_me_an_inner_class()):
    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()

稍后

mrh1997 提出了一个有趣的观点,关于使用这种技术创建的内部类的非传统继承。但看起来解决方案相当简单:

class Fatty():
    def do_sthg(self):
        pass
    
    class InnerFatty(object):
        pass
            
    def give_me_an_inner_fatty_class(self):
        class ExtendedInnerFatty(Fatty.InnerFatty):
            pass
        return ExtendedInnerFatty
                
fatty1 = Fatty()
fatty2 = Fatty()

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

print (issubclass(innerFattyClass1, Fatty.InnerFatty))
print (issubclass(innerFattyClass2, Fatty.InnerFatty))
143

你想从内部类的实例访问外部类的实例。解决这个问题的方法是使用工厂方法来创建内部类的实例,并把外部类的实例传递给它。

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()
104

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

需要注意的是,即使你创建了一个内部类的实例,外部类的实例不一定存在。

实际上,很多时候不建议使用嵌套类,因为嵌套并不意味着内部类和外部类之间有特别的关系。

撰写回答