Reputation: 7797
Consider these two python files:
# file1.py
global_var = "abc"
class A:
x = 1
glb = global_var
y = x + 1
class B:
z = 3
glb = global_var
zz = B.z
print(f"{A.B.z=}")
print(f"{A.zz=}")
# file2.py
global_var = "abc"
class A:
x = 1
glb = global_var
y = x + 1
class B:
z = y + 1
glb = global_var
zz = B.z
print(f"{A.B.z=}")
print(f"{A.zz=}")
One would expect them to do the exact same thing. But they don't!
$ python file1.py
A.B.z=3
A.zz=3
$ python file2.py
Traceback (most recent call last):
File "file2.py", line 4, in <module>
class A:
File "file2.py", line 8, in A
class B:
File "file2.py", line 9, in B
z = y + 1
NameError: name 'y' is not defined
B
access the global scope, but not the scope of A
?y = x + 1
should work but z = y + 1
should not? Is this a design decision, or undefined behavior of CPython?Upvotes: 2
Views: 565
Reputation: 7735
Chepner Already answer this one, but in short: Local variables are looked up in the global namespace so the way the classes are nested in your code sample work as expected.
It works as expected as stated above.
They don't work as for nested functions with the LEGB rule /realpython:
"When you define a class, you’re creating a new local Python scope. The names assigned at the top level of the class live in this local scope. The names that you assigned inside a class statement don’t clash with names elsewhere. You can say that these names follow the LEGB rule, where the class block represents the L level."
Also is not very common to nest a Class within another Class, normally you do Class inheritance as so:
class B(A):
y = A.y
z = y + 1
glb = global_var
Upvotes: 1
Reputation: 532418
From https://docs.python.org/3/reference/executionmodel.html:
Class definition blocks and arguments to exec() and eval() are special in the context of name resolution. A class definition is an executable statement that may use and define names. These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace. The namespace of the class definition becomes the attribute dictionary of the class. The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods – this includes comprehensions and generator expressions since they are implemented using a function scope. This means that the following will fail:
In the definition of B
, y
is an unbound local variable, and so is looked up in the global scope (where it is not defined), not in the namespace created by the enclosing class
statement.
A class
statement does not define a scope at all; it creates a namespace which is passed to the metaclass in order to construct a new class.
Upvotes: 2