Search code examples
pythonpython-3.xscoping

Why is one class-inside-a-class not in the scope of another class-inside-a-class?


Consider the following code:

from enum import Enum

class A(object):
    class B(object):
        blah = "foo"
        derp = "bar"

    class SubA(object):
        def __init__(self):                                                                                                                                                                                                            
            self.value = B.derp

This raises a NameError

>>> A.SubA()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 10, in __init__
    self.value = B.derp
NameError: name 'B' is not defined

On the other hand, replacing B.derp with A.B.derp makes the code work as desired.

Why does Python's scoping resolve this in the way it does, and why should this make sense in Python's design?


Solution

  • As described in PEP 227, the class body's scope is not available from inside other scopes nested inside it. So the reason you get a NameError for B in your example is the same reason you get a NameError in this case:

    class Foo(object):
        x = 88
        def foo(self):
            print(x)
    

    Functions defined in the class body (i.e., methods) don't have access to the class body scope; neither do nested classes (or functions nested inside those).

    A.B.derp works because A is in global scope, which is always accessible.

    However, note that even A.B.derp won't work if you try to use it directly in the class body:

    class A(object):
        class B(object):
            derp = 88
        class SubA(object):
            stuff = A.B.derp
    

    This won't work because the line referring to A.B.derp is executed during the process of creating A, so A doesn't exist yet and can't be referenced.