如何定义自由变量

How to define a free variable

提问人:ViM 提问时间:8/25/2022 最后编辑:petezurichViM 更新时间:8/25/2022 访问量:141

问:

我目前正在阅读 Fluent Python - Luciano Ramalho 一书(一本很棒的书 IMO)。

在有关装饰器和闭包的章节中,有一段代码:

def make_averager():
    series = []

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


avg = make_averager()

所以在这种情况下,是一个自由变量,我可以通过打印来验证这一点series

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

但是当我尝试重构: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()

要么 ,要么被视为free_variable。取而代之的是,现在是局部变量 (?),因为 returns 和 returns .seriestotalsumtotalsumavg.__code__.co_varnames('value', 'total', 'count')avg.__code__.co_freevars()

所以现在不再是 范围内的自由变量,除非我添加seriesaverager

series.append(value)

里面。这是可以理解的,因为我根本没有在里面调用,但我无法理解这两个变量发生了什么。averager(value)seriesaverager(value)

为什么 和 不被视为自由变量,如何将它们指定为自由变量?totalcount

python 作用域 自由变量

评论


答:

1赞 SargeATM 8/25/2022 #1

非本地总计,计数

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

为什么非局部变量使它们成为自由变量?

如果没有非局部变量,则默认为其创建局部变量。由于在函数的局部作用域内,它不再是一个自由变量。total += valuetotaltotalaverager

评论

0赞 ViM 8/25/2022
感谢您提供这个简单的解决方案。但是您能解释一下为什么在第一种方法中被认为是 a,而在第二种方法中则不被认为是 a?seriesnonlocaltotalsum
0赞 SargeATM 8/25/2022
从不赋值变量。(例如)翻译为查找变量持有的对象。是否在本地范围内?不。试试外部范围,是的。现在向 series 对象询问方法,以便我可以调用它。seriesseries = []series.appendseriesseriesappend