为什么Python的非本地关键字不像全局范围?

qnt*_*ntm 14 python python-3.x

在Python 3.3.1中,这适用于:

i = 76

def A():
    global i
    i += 10

print(i) # 76
A()
print(i) # 86
Run Code Online (Sandbox Code Playgroud)

这也有效:

def enclosing_function():
    i = 76
    def A():
        nonlocal i
        i += 10

    print(i) # 76
    A()
    print(i) # 86

enclosing_function()
Run Code Online (Sandbox Code Playgroud)

但这不起作用:

i = 76
def A():
    nonlocal i # "SyntaxError: no binding for nonlocal 'i' found"
    i += 10

print(i)
A()
print(i)
Run Code Online (Sandbox Code Playgroud)

nonlocal关键字状态的文档(强调添加):

非本地语句使列出的标识符引用最近的封闭范围中的先前绑定的变量.

在第三个例子中,"最近的封闭范围"恰好是全局范围.那为什么不起作用呢?

请仔细阅读本章

我注意到文档继续进行状态(强调添加):

除了全局(模块)范围nonlocal之外,[ ]语句允许封装代码重新绑定局部范围之外的变量.

但是,严格地说,这并不意味着我在第三个例子中所做的事情不应该起作用.

Mik*_*ler 7

名称的搜索顺序是LEGB,即Local,Enclosing,Global,Builtin.因此全局范围不是封闭范围.

编辑

来自文档:

非本地语句使列出的标识符引用最近的封闭范围中的先前绑定的变量.这很重要,因为绑定的默认行为是首先搜索本地名称空间.除了全局(模块)范围之外,该语句还允许封装代码重新绑定局部范围之外的变量.

  • 因为http://docs.python.org/3/reference/simple_stmts.html#nonlocal说:"语句[`nonlocal`]允许封装代码重新绑定局部作用域之外的变量****全局(模块) ) 范围." (重点补充) (3认同)
  • 为什么不?它包含了一切。 (2认同)
  • 在我看来,根本不应该使用 `global`,除了一些非常特殊的情况,比如我曾经使用过的嵌入在 C 中。如果您足够努力并且您的代码会更好,那么总有没有“全局”的解决方案。因此,在我看来,将“非本地”扩展到全局范围是错误的。 (2认同)

jfs*_*jfs 5

为什么模块的作用域被认为是全局的而不是封闭的?对于其他模块来说它仍然不是全局的(好吧,除非你这样做from module import *),是吗?

如果你将一些名称放入 的module命名空间中;它在任何使用moduleie 的模块中都是可见的,对于整个 Python 进程来说它是全局的。

一般来说,您的应用程序应该使用尽可能少的可变全局变量。请参阅为什么全局变量不好?:

  • 非局域性
  • 无访问控制或约束检查
  • 隐式耦合
  • 并发问题
  • 命名空间污染
  • 测试和限制

nonlocal因此,如果允许意外创建全局变量,那将是很糟糕的。如果要修改全局变量;您可以global直接使用关键字。

  • global最具破坏性:可能会影响程序中任何地方对该模块的所有使用
  • nonlocal破坏性较小:受outer()函数作用域限制(在编译时检查绑定)
  • 不声明(局部变量)是破坏性最小的选项:受inner()函数作用域限制

nonlocal您可以在PEP: 3104 Access to Names in Outer Scopes中了解背后的历史和动机。

  • @NadiRSampaoli:我不明白你的评论与我的答案有什么关系,我的答案是:全局变量很糟糕,因此如果非本地意外创建全局变量,那就不好了。 (2认同)

Mar*_*cin 2

答案是全局作用域不包含任何东西——它对所有事物都是全局的。global在这种情况下请使用关键字。