I have created a nested closure which looks as below:
def incrementer(n):
def inner(start):
current = start
def inc():
nonlocal current
current = n
return current
return inc
return inner
fn = incrementer(2)
Now, when I print value of co_freevars for fn I get below output:
print(fn.__code__.co_freevars) -> ('n',)
My understanding is that it should be ('current', 'n') because there are 2 free variables
here.
Why print(fn.__code__.co_freevars) is not printing ('current', 'n')?
CodePudding user response:
You define current in inner, so it's a normal local variable there. current is a closure variable in inc.
Consider:
inner = incrementer(2)
inc = inner(1)
print(inner.__code__.co_freevars)
print(inc.__code__.co_freevars)
Output:
('n',)
('current', 'n')
Another example to drive home the point:
def outer():
var1 = 1
var2 = 2
var3 = 3
var4 = 4
def middle():
var1
var2
def inner():
var2
var4
return inner
return middle
middle = outer()
inner = middle()
print(outer.__code__.co_freevars)
print(middle.__code__.co_freevars)
print(inner.__code__.co_freevars)
Output:
()
('var1', 'var2', 'var4')
('var2', 'var4')
first print:
outer has no closure variables.
second print:
var1, var2 and var4 are used in middle and come from an outer scope. Yes, var4 is used in middle. In the definition of inner, which is defined inside of middle.
third print:
var2 and var4 are used in inner and come from an outer scope.
