4

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>", 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.

asked Jun 28, 2010 at 9:12

3 Answers 3

5

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
answered Jun 28, 2010 at 9:29
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks - but are there any references about internal implementation? I'd like to see how to parser actually works. Is it so that Python creates dictionary/struct for every scope and only looks for the outer scope if there is nothing in inner one? Just want to clear my thoughts.
this is not a parser issue, it's a runtime "find closest scope with a name matching x" thing.
1

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.

answered Jun 28, 2010 at 14:32

Comments

0

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

answered Jun 28, 2010 at 9:30

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.