7

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?

4
  • This thread stackoverflow.com/questions/12810426/… refers to the same issue, but no strong explanation is given. PEP-0227 and python 2.7 execution model do not make any difference between of function block or a class block Commented Nov 22, 2013 at 15:25
  • This is a common scoping issue. Notice the difference in the namespaces between the following: <function f at 0x1092a80c8> and <class __main__.C at 0x1092946d0>. The difference is the __main__ namespace. Commented Nov 23, 2013 at 10:18
  • Also, this is very closely related to stackoverflow.com/questions/12810426/… Commented Nov 23, 2013 at 10:21
  • @VooDooNOFX I still don't get your explanation. A class is a code block and a variable assigned anywhere in a code block is local. This is not what I observe. It looks like there is a static binding for functions only, but I do not find any reference to this behavior in the Python documentation. Commented Nov 23, 2013 at 13:53

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.