pythonpython-3.xclosuresfree-variable

`del` statement and free variables


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 than NameError: 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


Solution

  • 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.