python - 为什么这个闭包不修改封闭范围内的变量?

标签 python closures generator

这点 Python 不行:

def make_incrementer(start):
    def closure():
        # I know I could write 'x = start' and use x - that's not my point though (:
        while True:
            yield start
            start += 1
    return closure

x = make_incrementer(100)
iter = x()
print iter.next()    # Exception: UnboundLocalError: local variable 'start' referenced before assignment

我知道如何解决这个错误,但请耐心等待:

这段代码运行良好:

def test(start):
    def closure():
        return start
    return closure

x = test(999)
print x()    # prints 999

为什么我可以读取闭包内的 start 变量但不能写入? 什么语言规则导致对 start 变量的这种处理?

更新:我发现这篇 SO 帖子相关(答案比问题更重要):Read/Write Python Closures

最佳答案

每当您在函数内部分配变量时,它将是该函数的局部变量。 start += 1 行正在为 start 分配一个新值,因此 start 是一个局部变量。由于存在局部变量 start,因此当您第一次尝试访问它时,该函数不会尝试在全局范围内查找 start,因此您会看到错误。

在 3.x 中,如果您使用 nonlocal 关键字,您的代码示例将起作用:

def make_incrementer(start):
    def closure():
        nonlocal start
        while True:
            yield start
            start += 1
    return closure

在 2.x 上,您通常可以通过使用 global 关键字来解决类似的问题,但这在这里不起作用,因为 start 不是全局变量。

在这种情况下,您可以执行建议的操作 (x = start),也可以使用可变变量修改并生成内部值。

def make_incrementer(start):
    start = [start]
    def closure():
        while True:
            yield start[0]
            start[0] += 1
    return closure

关于python - 为什么这个闭包不修改封闭范围内的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7535857/

相关文章:

python - 列表中的 Mergesort Python 数字排序

python - 为什么分配给 sys.modules[__name__] 后 __name__ 的值会发生变化?

javascript - 我如何在我的代码中使用闭包?

javascript - 如何使用 Mocha 测试嵌套 ES6 生成器?

jquery - Rails3 应用程序使用 jquery 但未将其包含在 Gemfile 中,应该吗?

python - 如何扩展顶级QTreeview项目

Python激活环境变量

javascript - Javascript 循环内的事件处理程序 - 需要闭包吗?

swift - Swift 闭包中的 `self`

python - 如何将列表值与字典键进行比较并使用 python 创建一个新字典