0

How can I assign a variable from an outer class to the inner? Here is my best attempt:

in [1]: class one:
   ...:     x = 1
   ...:     class two:
   ...:         y = x
   ...:         
--------------------------------------------------------------------------- 
NameError: name 'x' is not defined

I am confused as to why this doesn't work, but Python has no problem with this syntax:

In [1]: x = 1
In [2]: class one:
   ...:     y = x
   ...:     class two:
   ...:         z = x
   ...:         

In [3]: one.two.z
Out[3]: 1
kilojoules
  • 9,768
  • 18
  • 77
  • 149
  • How can I rephrase this question? Edit: Thanks Jeremy Banks I now see this is an outer class. – kilojoules Jan 28 '16 at 23:14
  • 3
    Why are you even putting one class inside another? There's almost never a reason to do that in Python. – user2357112 Jan 28 '16 at 23:16
  • 1
    Related: [Nested Python class needs to access variable in enclosing class](http://stackoverflow.com/questions/6391645/nested-python-class-needs-to-access-variable-in-enclosing-class) – Jeremy Jan 28 '16 at 23:16
  • I am experimenting with different openmdao configurations – kilojoules Jan 28 '16 at 23:17
  • 1
    @kilojoules I'm not certain if "outer class" is a formal/standard term for this, but it's one I've seen used elsewhere and is hopefully a bit clearer. I always get Python's behaviour in this context mixed up; it's not very obvious. – Jeremy Jan 28 '16 at 23:17
  • 1
    In the second example, `'x' is not defined` within the scope of `y`. In the first example, `x` is defined in the global scope. – OneCricketeer Jan 28 '16 at 23:26

2 Answers2

0

What you are doing makes no sense to me, anyway, you can access outer class's instance variable by passing its instance into inner class. Nested classes are not recommended. You can use Inheritance to achieve this.

class Outer:
    def __init__(self):
        self._x = 1

    def create_inner(self):
        """passes outer class instance into Inner"""
        return Outer.Inner(self)

    class Inner:
        def __init__(self, outer):
            self._outer = outer
            self._y = self._outer._x

        def print_y(self):
            print self._y


outer = Outer()
inner = outer.create_inner()
inner.print_y()

Output:

1
Haifeng Zhang
  • 30,077
  • 19
  • 81
  • 125
-1

When a class definition is encountered Python will execute the body without second thought.

First, it will execute class one, while executing the body (and before actually creating the class), it will encounter class two so it will execute that.

Inside class two it will see a reference to one which still does not exist, hence a NameError will be raised.

One simple way to see the difference in the way Python treats classes/functions is by wrapping the second class definition inside a function. Since Python only compiles functions and doesn't execute them, class one is going to get created:

class one:
    x = 1
    def wrap():
        class two:
            y = one.x
        one.two = two

Now one exists as a class. If you execute one.wrap the second class definition is going to get executed, the one class is going to be found and then, just to follow along with your original example; I set the class two as an attribute of one to get the same effect you were going for.

As a result, name resolution works fine and class two now has an attribute of class one:

one.wrap()

one.two.y
Out[22]: 1

Do Note: Moving the second class outside of the first class definition works too, but that's besides the point.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
  • Great! One small note to others - it should be `def wrap(self):`. otherwise it will throw a number of arguments error. – kilojoules Jan 28 '16 at 23:52
  • 1
    @kilojoules The `TypeError` is raised if you instantiate. If not you should be good to go. Either way, this example with the nested `class` in the `def` was not meant as something that you should use but more so in order to illustrate how Python *executes classes* vs *compiles functions*. – Dimitris Fasarakis Hilliard Jan 28 '16 at 23:57