Testing some Python code today I tried the following code:
(The following runs on Python 3.2+, although previous versions will raise a SyntaxError
when del
is used and a variable is referenced in an enclosing scope)
def x():
N = 200
def y():
print(N)
del N
y()
x()
NameError: free variable 'N' referenced before assignment in enclosing scope
As you can see, Python does not raises NameError: global name 'N' is not defined
, and that made me wondering about one thing which is:
when del
statement used withing the enclosing scope of a function to delete a free variable that's used inside a nested function like y
function here and thereafter if that free variable in our case N
was deleted through del
statement in the enclosing scope, what del
actually does is to delete the name's (N
) value and keeps it bound to the enclosing scope ?
A) Is that why it raises:
NameError: free variable 'N' referenced before assignment...
rather thanNameError: global name 'N' is not defined
?B) How does
del
actually delete a name? Does it unbind its value and keep it in a scope ?
I found a similar case here
It works like this: when you write print(N)
inside y
but do not assign to N
in y
, that means that at the time y
is defined, Python looks in its enclosing scopes to find the nearest one where the name N
is assigned. It doesn't matter whether the assignment to N
happens before or after the definition of y
, or whether it's later undone with a del
; it just looks for the nearest enclosing scope where an assignment to N
exists. In this case, since N
is assigned inside x
, y
essentially makes a little note saying "when I need to get N
, I will look in the scope of x
".
So when you actually call y
, it looks for N
in the scope of x
. If it isn't there, you get the error. Note that you get this same error without del
if you move the N = 100
line after the call to y
.