【问题标题】:Python inner function variable scopePython内部函数变量范围
【发布时间】:2019-07-12 12:53:01
【问题描述】:

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

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  

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

【问题讨论】:

    标签: python closures


    【解决方案1】:

    [...] 是否有允许从内部修改 foo 的关键字?

    确实有这样一个关键字: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" 标识符 ("," 标识符)*

    nonlocal 语句导致列出的标识符引用最近的封闭范围内的先前绑定的变量,不包括全局变量。这很重要,因为绑定的默认行为是首先搜索本地命名空间。该语句允许封装代码重新绑定全局(模块)范围之外的局部范围之外的变量。

    与全局语句中列出的名称不同,在非本地语句中列出的名称必须引用封闭范围内的预先存在的绑定(无法明确确定应在其中创建新绑定的范围)。

    非本地语句中列出的名称不得与本地范围内的预先存在的绑定发生冲突。

    至于why 部分:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-13
      • 2013-10-12
      • 2019-10-05
      • 2012-06-06
      • 2016-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多