In python (tested on 2.7.6) all variables are statically bound to a scope at compile time. This process is well described in http://www.python.org/dev/peps/pep-0227/ and http://docs.python.org/2.7/reference/executionmodel.html
It is explicitly stated that "If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block."
A function is a code block so the following code with fail because x
is assigned after its use (so at compile time it is defined local
because it is assigned somewhere in the function, but at execution
time, it is used before being bound).
x = 1
def f():
print x
x = 2
print x
>>> f()
Traceback (most recent call last):
File "<pyshell#46>", line 1, in <module>
f()
File "<pyshell#45>", line 2, in f
print x
UnboundLocalError: local variable 'x' referenced before assignment
A class is also a code block, so we should observe exactly the same behavior. But this is not what I observe. Look at this example:
x = 1
class C():
y = x + 10
x = 2
def __init__(self):
print C.y
>>> C.x
2
>>> C.y
11
>>> C()
11
<__main__.C instance at 0x00000000027CC9C8>
As the class definition is a code block, any assignment within this
block should make the variable local. So x
should be local to the
class C
, so y = x + 10
should result in an UnboundLocalError
.
Why there is not such error?
Yes - it seems that the documentation is rather misleading. A class definition doesn't actually work quite the same as other normal blocks:
global_one = 0
class A(object):
x = global_one + 10
global_one = 100
y = global_one + 20
del global_one
z = global_one + 30
a = A()
print a.x, a.y, a.z, global_one
results in: 10, 120, 30, 0
if you try the same thing with a function, you get an UnboundLocalError
on your first access of global_one
.
The reason for this is that class definitions as normal have access to the parent scope, however, all name assignments do NOT modify a local scope, but in fact are captured into the class's data attributes dictionary. There are hints about this in the documentation, but it's certainly not obvious.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With