How does Python variable scoping works?
This wants me to dig deeper in Python sources, but since there are many people on SO that already done that, I would love to hear their pointers.
>>> import os
>>> def scope():
... print os
... import os
...
>>> scope()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin&开发者_开发问答gt;", line 2, in scope
UnboundLocalError: local variable 'os' referenced before assignment
It seems to me that when parser interprets the file, it automatically creates local scope for scope function, that makes os "detached" from global scope.
Is it true? Anyone care to point me where I can find more about scope implementation?
EDIT: Also, this is not special case of imports, this works for usual variables too.
When you call scope()
Python sees that you have a local variable called os
used inside your method (from the import
inside scope
) so this masks the global os
. However when you say print os
you haven't reached the line and executed the local import yet so you see the error regarding reference before assignment. Here are a couple of other examples that might help:
>>> x = 3
>>> def printx():
... print x # will print the global x
...
>>> def printx2():
... print x # will try to print the local x
... x = 4
...
>>> printx()
3
>>> printx2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in printx2
UnboundLocalError: local variable 'x' referenced before assignment
And going back to your os
example. Any assignment to os
has the same effect:
>>> os
<module 'os' from 'C:\CDL_INSTALL\install\Python26\lib\os.pyc'>
>>> def bad_os():
... print os
... os = "assigning a string to local os"
...
>>> bad_os()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in bad_os
UnboundLocalError: local variable 'os' referenced before assignment
Finally, compare these 2 examples:
>>> def example1():
... print never_used # will be interpreted as a global
...
>>> def example2():
... print used_later # will be interpreted as the local assigned later
... used_later = 42
...
>>> example1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in example1
NameError: global name 'never_used' is not defined
>>> example2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in example2
UnboundLocalError: local variable 'used_later' referenced before assignment
Lexical scoping is a common thing and most well designed languages, whether interpreted or compiled use it.
I had not tried this in a while, but note the nifty "global" keyword, and its use below:
o = 1
def foo():
global o
o = 2
foo()
print o
Without the "global" line, the modification to o is localized, and "print o" prints 1. With the "global o" line included, it prints 2. We call this way that my function (without the global o) above would have its own variables. The global thing above is a way to specifically request an exception to the normal lexical scoping.
True lexical scoping is something that Python 1.0 lacked, and which Python has had for a long time (since at least 1.6, if I remember correctly). There were only two scopes, local and global, and any intermediate scopes were inaccessible.
Any binding of a variable inside a function makes the variable local to that function. import
, def
and class
are all equivalent to assignment in this respect.
So yes, when the compiler compiles your file it creates a local variable os
which is scoped separately from the global os
.
See the Python tutorial for more information. In particular http://docs.python.org/tutorial/classes.html section 9.2
精彩评论