Access outer class from inner class in python

2020-01-24 11:48发布

I have a situation like so...

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

How can I access the Outer class's method from the Inner class?

9条回答
可以哭但决不认输i
2楼-- · 2020-01-24 11:56

maybe I'm mad but this seems very easy indeed - the thing is to make your inner class inside a method of the outer class...

def do_sthg( self ):
    ...

def messAround( self ):

    outerClassSelf = self

    class mooble():
        def do_sthg_different( self ):
            ...
            outerClassSelf.do_sthg()

Plus... "self" is only used by convention, so you could do this:

def do_sthg( self ):
    ...

def messAround( outerClassSelf ):

    class mooble():
        def do_sthg_different( self ):
            ...
            outerClassSelf.do_sthg()

It might be objected that you can't then create this inner class from outside the outer class... but this ain't true:

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

then, somewhere miles away:

blob = Bumblebee().giveMeAnInnerClass()()
blob.do_sthg_different()    

even push the boat out a bit and extend this inner class (NB to get super() to work you have to change the class signature of mooble to "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()

later

mrh1997 raised an interesting point about the non-common inheritance of inner classes delivered using this technique. But it seems that the solution is pretty straightforward:

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 ))
查看更多
劳资没心,怎么记你
3楼-- · 2020-01-24 11:58

You're trying to access Outer's class instance, from inner class instance. So just use factory-method to build Inner instance and pass Outer instance to it.

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()
查看更多
虎瘦雄心在
4楼-- · 2020-01-24 12:01

Do you mean to use inheritance, rather than nesting classes like this? What you're doing doesn't make a heap of sense in Python.

You can access the Outer's some_method by just referencing Outer.some_method within the inner class's methods, but it's not going to work as you expect it will. For example, if you try this:

class Outer(object):

    def some_method(self):
        # do something

    class Inner(object):
        def __init__(self):
            Outer.some_method()

...you'll get a TypeError when initialising an Inner object, because Outer.some_method expects to receive an Outer instance as its first argument. (In the example above, you're basically trying to call some_method as a class method of Outer.)

查看更多
Animai°情兽
5楼-- · 2020-01-24 12:01

Expanding on @tsnorri's cogent thinking, that the outer method may be a static method:

class Outer(object):

    @staticmethod
    def some_static_method(self):
        # do something

    class Inner(object):
        def __init__(self):
            self.some_static_method()    # <-- this will work later

    Inner.some_static_method = some_static_method

Now the line in question should work by the time it is actually called.

The last line in the above code gives the Inner class a static method that's a clone of the Outer static method.


This takes advantage of two Python features, that functions are objects, and scope is textual.

Usually, the local scope references the local names of the (textually) current function.

...or current class in our case. So objects "local" to the definition of the Outer class (Inner and some_static_method) may be referred to directly within that definition.

查看更多
手持菜刀,她持情操
6楼-- · 2020-01-24 12:10

The methods of a nested class cannot directly access the instance attributes of the outer class.

Note that it is not necessarily the case that an instance of the outer class exists even when you have created an instance of the inner class.

In fact, it is often recommended against using nested classes, since the nesting does not imply any particular relationship between the inner and outer classes.

查看更多
欢心
7楼-- · 2020-01-24 12:12

I found this.

Tweaked to suite your question:

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)

I’m sure you can somehow write a decorator for this or something

related: What is the purpose of python's inner classes?

查看更多
登录 后发表回答