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
Questions:
- Why can the definition of
B
access the global scope, but not the scope ofA
? - Why is it that
y = x + 1
should work butz = y + 1
should not? Is this a design decision, or undefined behavior of CPython? - What are the general rules for what variables / scope are accessible when calculating the values of class variables? When should I worry about which scope I'm allowed to use in defining my class variables?
self.x
orClassName.x
to access a class variablex
in a method. – user2357112 supports Monicaclass
statement occur in the global scope, not the closest containing scope. (In the case ofB
, the global scope is the closest containing scope anyway, because aclass
statement does not create a new scope.)y
isn't defined, because the definition ofB
doesn't look in the definition ofA
. – chepnerlocals().keys()
within definitions ofA
andB
does show the respective class variables in the local scope. And actually, it has to, when you think of it, otherwise all class variables would end up in the module scope. So there is a class scope, but it is a temporary scope, which exists only while building the class. – zvonelocals
is returning that namespace, but that doesn't mean name resolution uses it. – chepner