Python 内部函数变量作用域

标签 python closures

我在编写的有关变量范围的内部函数时遇到了问题。我已经设法简化代码以指出确切的问题。所以开始:

def outer(foo):
    def inner(bar):
        print(foo)
        print(bar)
    return inner 


if __name__ == "__main__":
    function = outer("foo")
    function("bar")

我将得到预期的输出:

foo
bar 

但是,如果我尝试重新分配 foo,则会出现错误:

def outer(foo):
    def inner(bar):
        foo = "edited " + foo
        print(foo)
        print(bar)
    return inner

给出:

UnboundLocalError: local variable 'foo' referenced before assignment  

这让我想起了全局变量,您可以在其中正常“读取”它们,但要“写入”您必须执行“global variable; variable=...”。是一样的情况吗?如果是这样,是否有一个关键字允许从内部修改 foo?还有为什么?当然,一旦我创建了函数,那么 foo 就固定用于该函数。 IE。不是全局性的。这里避免了什么问题?

最佳答案

[...] is there a keyword that allows modification of foo from within inner?

确实有这样一个关键字:nonlocal

def outer(foo):
    def inner(bar):
        nonlocal foo
        foo = "edited " + foo
        print(foo)
        print(bar)
    return inner

outer("foo")("bar")

输出:

edited foo
bar

来自docs :

nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.

Names listed in a nonlocal statement, unlike those listed in a global statement, must refer to pre-existing bindings in an enclosing scope (the scope in which a new binding should be created cannot be determined unambiguously).

Names listed in a nonlocal statement must not collide with pre-existing bindings in the local scope.

至于为什么部分:

代码块中的任何赋值 (x = y) 都会将变量的范围更改为当前范围。因此,要引用和修改 (*) 来自全局范围的变量,我们需要关键字 global,但在这种情况下,我们需要来自“最近的封闭”范围的变量,因此我们需要关键字 非本地

(*) 通过赋值修改;可变全局变量仍然可以使用它们各自的方法修改,而无需全局/非局部关键字。

关于Python 内部函数变量作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57007407/

相关文章:

javascript - NodeJS 回调之外的变量

objective-c - swift 中的闭包可以用于两个类之间的通信吗?

java - Java 8 闭包存储在哪里?

python - 从 CSV 文件中计算男性和女性的数量

python - 根目录IO错误: [Errno 13] Permission denied:

java - Jython - PyObject 的类转换异常

javascript - 为什么这个闭包无法访问 'this' 关键字? - jQuery

python - 在 Python 中执行 N*M 迭代的最快算法

python - 将python程序转换为可执行文件

javascript - Javascript 中 for 循环内的闭包结果令人困惑