The scope of the name a
is over the entirety of the function f
, and is purely static. It is not at all correct to say that "there is a 50% chance that the print statement is outside the scope of a
". "Not in scope" is not the only reason why a name lookup can fail.
Note the error you get from this function:
>>> def foo():
... print a
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
NameError: global name 'a' is not defined
It's not the same error you get when your function has executed del a
. In my foo
, a
was not defined in the local scope of foo
, so name lookup proceeded to the global scope, where a
wasn't found either, so we get an exception about there not being a global a
.
The error you get clearly states that Python is aware that the name a
is a local variable of f
. However it has no value, because you deleted it. (Normally this would only happen because you try to read a local variable before you've ever written to it, which is why the error message is worded the way it is)
Note also this case:
a = 3
>>> def bar():
... a = 1
... del a
... print a
...
>>> bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in bar
UnboundLocalError: local variable 'a' referenced before assignment
Python complains about the local a
not having a value. If a
were simply not in the local scope, it would have looked up a
globally and found the 3
:
>>> a = 8
>>> def baz():
... print a
...
>>> baz()
8
This is different behaviour than you get when you del
things from the global scope:
>>> a = 12
>>> del a
>>> print a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
Here you get an exception as if a
had never existed. The reason for the difference is because the local scope of a function is static. If a function contains an assignment to a name, then that name is locally scoped over the entirety of the function's body1. Even before the first assignment, or after you've used del
to get rid of it, lookup of that name in that function will try to get the value of the local variable.
1 Unless the name has been declared global
or nonlocal
.