Differences between class block and function block in python
Asked Answered
T

3

8

Code 1

x = 0

class Foo:
    print(x)
    x = 1
    print(x)

print(x)

Result 1

0
1
0

Code 2

x = 0

def foo():
    print(x)
    x = 1
    print(x)

foo()

Result 2

UnboundLocalError: local variable 'x' referenced before assignment.

Why can x reference objects from two namespaces in class block?
I don't understand why Code 1 not throw an UnboundLocalError.
Inconsistency between function and class bother me.


Update:

After reading the Python Docs several times, I still cannot understand the scoping rules.

The following are blocks: a module, a function body, and a class definition. ...[skip]...

If a name is bound in a block, it is a local variable of that block, unless declared as nonlocal. If a name is bound at the module level, it is a global variable. (The variables of the module code block are local and global.) If a variable is used in a code block but not defined there, it is a free variable.

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. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.

Tetchy answered 10/10, 2012 at 0:45 Comment(0)
S
6
x = 0

class Foo:
    print(x)   # Foo.x isn't defined yet, so this is the global x
    x = 1      # This is referring to Foo.x
    print(x)   # So is this

print(x)

x = 0

def foo():
    print(x)   # Even though x is not defined yet, it's known to be local
               # because of the assignment
    x = 1      # This assignment means x is local for the whole function
    print(x)

foo()
Sciamachy answered 10/10, 2012 at 0:49 Comment(3)
Can I have local var in class block?Tetchy
you can simply add "global x" before you use itVirtue
@Yang, sure - if you need it to be a global variable. I think most often when people see this error, they mean it to be a local, but accidentally use it before it's defined. sprinkling global in there just to get the program to run isn't really a good idea.Sciamachy
G
1

For the examples to be comparable, don't forget to use the global statement:

def foo():
    global x
    print(x)
    x = 1
    print(x)

In this way you won't get the UnboundLocalError.

Grab answered 10/10, 2012 at 0:52 Comment(0)
N
1

The class-block doesn't know "local" variables, just class-variables. They are different from local variables in that they aren't forgotten after execution of the block; they will remain as fields in the class. Local and class variables are handled differently in more than just this aspect, so it isn't too surprising that no unbound error is raised. After all you do not have an undefined local variable shadowing the global variable. As a result, access to the global variable before defining the class variable is no problem.

Maybe the compiler should somehow warn about this as well, but currently it doesn't.

Nevanevada answered 10/10, 2012 at 0:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.