简体   繁体   中英

How to define a free variable

I am currently reading the book Fluent Python - Luciano Ramalho (a great book IMO).

In the chapter about decorators and closures, there is a following piece of code:

def make_averager():
    series = []

    def averager(value):
        series.append(value)
        total = sum(series)
        return total/len(series)
    return averager


avg = make_averager()

So in this case, series is a free variable, and I can verify this by printing

>>> avg.__code__.co_varnames
('new_value', 'total')
>>> avg.__code__.co_freevars
('series',)

But when I tried refactoring the make_averager() :

def make_averager():
    series = []
    total = 0
    count = 0

    def averager(value):
        total += value
        count += 1
        return total/count
    return averager

avg = make_averager()

either series , total or sum is considered a free_variable. Instead, total and sum are now local variables (?) since avg.__code__.co_varnames returns ('value', 'total', 'count') and avg.__code__.co_freevars returns () .

So now series is now no longer a free-variable in the scope of averager , unless I add

series.append(value)

inside averager(value) . This is understandable since I don't call series at all inside averager(value) , but I couldn't understand what's happening with those 2 variables.

Why are total and count not considered as free-variables, and how do I assign them as free-variables?

nonlocal total, count

def averager(value):
    nonlocal total
    nonlocal count
    total += value
    count += 1
    return total/count

Why does nonlocal make them free variables?

Without nonlocal, total += value assigns to total which by default creates a local variable. Since total is in the local scope of the function averager , it is no longer a free variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM