Home > database >  How free variable value is determined within nested closure?
How free variable value is determined within nested closure?

Time:02-24

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.

  • Related