Why static binding works differently for class and function?
Asked Answered
R

1

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?

Raggedy answered 22/11, 2013 at 15:17 Comment(4)
This thread #12810926 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 blockRaggedy
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.Chirrupy
Also, this is very closely related to #12810926Chirrupy
@Chirrupy 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.Raggedy
V
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.

Vasoconstrictor answered 24/11, 2013 at 7:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.