scope - Python的非本地取决于层次结构?

标签 scope python-3.x closures

这个问题是 a question about Python variable scope 的后续问题。 .其他问题 q1 , q2answers可以在 SO 上找到,甚至更多。
官方Python documentation , 和 PEP 3104应该解释细节,但对我来说,它们似乎并不完全不言自明。

我要解决的主题是重构包含 nonlocal 的代码/global通过将该代码向上/向下移动一级层次结构。

我不明白的是 Python 引用中这句话的含义:

Names listed in a nonlocal statement, unlike to 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).



给定以下关于全局范围的代码:
var = 0
def outer():
    global var                  # line A
    var = 1
    def inner():
        nonlocal var            # line B
        var = 2

        print('inner:', var)

    inner()
    print('outer:', var)

outer()
print('main:', var)

执行引发错误:
SyntaxError: no binding for nonlocal 'var' found

该代码有效(当然,如果注释掉了 A 行,则具有不同的语义:
inner: 2
outer: 2
main: 0

或 B 行被注释掉:
inner: 2
outer: 1
main: 1

然而,在上面的例子中,由于 nonlocal应该将 var 绑定(bind)到“封闭范围”,我原以为 A 行将外部/var 绑定(bind)到全局范围,B 行然后查找外部/var 并将内部/var 重新绑定(bind)到 global/var。相反,它似乎根本找不到它(我想是由于 A 行中的重新绑定(bind))并引发了错误。

我期望的结果是:
inner: 2
outer: 2
main: 2

这只是 Python 中范围界定的困惑心态的又一个例子吗?

或者,为了使这是一个 build 性的问题:
  • 如何编写这样的示例,使函数驻留在哪个级别无关紧要(必须交换 globalnonlocal,反之亦然)?
  • 如果这些函数位于一个中间的、未知的层次结构中,outer() 的作者怎么能做到?更改最外层(在本例中为全局)级别和 inner() 的代码水平必须被触及? -

  • 在我对这门语言的谦虚理解中,应该避免像这样的结构(依赖于闭包)。其他人已经建议使用其他语言功能(classesfunc attrs)来实现这种上下文敏感性。

    最佳答案

    globalnonlocal不打算合并。它们的含义不同:

  • global表示名称存在于模块级别
  • nonlocal表示名称存在于外部词法函数范围内

  • 您得到原始异常的原因是您告诉 Python var是非本地的(意味着它在外部函数定义中),但有 没有功能级绑定(bind)对于 var在任何外部函数定义中,因为您在外部函数中告诉 Python var是全局性的。

    关于scope - Python的非本地取决于层次结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8050502/

    相关文章:

    python - 是否有将列表(可迭代)分成两部分的单一调用方法?

    python-3.x - 如何知道Firestore Python中是否存在文档?

    JavaScript 闭包问题

    javascript - 如何将 Proxy 对象作为上下文传递给 JavaScript 中的闭包

    c++ - 有人可以用 C++ 解释这个算法吗?

    c++ - 应该是本地的变量正在发挥全局作用

    c++ - 多文件程序中的作用域

    python - 关于 Python 变量作用域的困惑

    grails - 如何重构Groovy中作为方法调用参数的闭包中的重复项?

    python - 如何为 anaconda 1.9.1 和 Python 3.3.4 安装 Matplotlib?