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

Why doesn't Python's nonlocal keyword like the global scope?

在python 3.3.1中,这项工作:

1
2
3
4
5
6
7
8
9
i = 76

def A():
    global i
    i += 10

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

这也适用于:

1
2
3
4
5
6
7
8
9
10
11
def enclosing_function():
    i = 76
    def A():
        nonlocal i
        i += 10

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

enclosing_function()

但这不起作用:

1
2
3
4
5
6
7
8
i = 76
def A():
    nonlocal i #"SyntaxError: no binding for nonlocal 'i' found"
    i += 10

print(i)
A()
print(i)

nonlocal关键字状态的文档(添加了重点):

The nonlocal statement causes the listed identifiers to refer to
previously bound variables in the nearest enclosing scope.

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

请读一下这个

我确实注意到文档将继续状态化(强调已添加):

The [nonlocal] statement allows encapsulated code to
rebind variables outside of the local scope besides the global
(module) scope.

但是,严格来说,这并不意味着我在第三个例子中所做的不应该奏效。


名称的搜索顺序是legb,即本地、封闭、全局、内置。因此全局范围不是封闭范围。

编辑

从文档中:

The nonlocal statement causes the listed identifiers to refer to
previously bound variables in the nearest enclosing scope. 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.


答案是,全局范围不包含任何内容——它对所有内容都是全局的。在这种情况下使用global关键字。


why is a module's scope considered global and not an enclosing one? It's still not global to other modules (well, unless you do from module import *), is it?

如果您在module的名称空间中输入了一些名称,那么它在使用module的任何模块中都是可见的,也就是说,它对于整个python进程是全局的。

一般来说,您的应用程序应该使用尽可能少的可变全局变量。明白为什么全球股市不好吗?:

  • 非本地
  • 没有访问控制或约束检查
  • 隐式耦合
  • 并发问题
  • 命名空间污染
  • 测试和限制
  • 小精灵

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

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

      你可以在《政治公众人物:3104》中读到nonlocal背后的历史和动机。访问外部作用域中的名称。


      这取决于边界情况:

      非本地人有一些我们需要注意的敏感区域。首先,与global语句不同的是,在计算非本地名称时,非本地名称必须事先在封闭定义的作用域中进行分配,否则将出现错误,无法通过在封闭作用域中重新分配它们来动态创建它们。实际上,在调用或嵌套函数之前,在函数定义时对它们进行检查

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      >>>def tester(start):
            def nested(label):
               nonlocal state   #nonlocals must already exist in enclosing def!
               state = 0
               print(label, state)
            return nested
      SyntaxError: no binding for nonlocal 'state' found

      >>>def tester(start):
            def nested(label):
                global state   #Globals dont have to exits yet when declared
                state = 0      #This creates the name in the module now
                print(label, state)
            return nested

      >>> F = tester(0)
      >>> F('abc')
      abc 0
      >>> state
      0

      其次,非本地将范围查找限制为仅封闭def;非本地不会在封闭模块的全局范围或所有def之外的内置范围内查找,即使它们已经存在:

      例如:

      1
      2
      3
      4
      5
      6
      7
      8
      >>>spam = 99
      >>>def tester():
            def nested():
               nonlocal spam  #Must be in a def, not the module!
               print('current=', spam)
               spam += 1
            return nested
      SyntaxError: no binding for nonlocal 'spam' found

      一旦您认识到Python通常不知道在其中创建一个全新名称的封闭范围,这些限制就有意义了。在前面的列表中,应该在测试人员中分配垃圾邮件,还是在外部分配模块?因为这是不明确的,所以python必须在函数创建时解析非局部变量,而不是在函数调用时。