Python3 使用 nonlocal keyword 实现保存状态的嵌套函数

前言:
最近阅读一本书《代码之髓》, 其中篇章:《7.3 静态作用域是完美的吗》
介绍了 Python3 的 nonlocal 关键字, 从12月将工作语言升级到Python3后,
才从一本讲述编程语言概念的书籍里知晓这个 nonlocal -_-b

首先写个小Demo:

该小例子, 如果使用 Python2(至少2.6以上)时, 在嵌套的作用域里, 将外部的局布
作用域里里的x引入进来, 需要使用一个 list 或者其他序列结构将 x 的
引用保存, 然后在嵌套作用域里(例子中的 x_add)从序列引用里拿出, 然后
加1操作.

这是一个简单的闭包(有状态的函数)例子, 在Python2 像 Lua 或者 js 那样
自然地写一个实现需要用序列保存引用的 trick 方式~~

Lua代码是这么实现的:

nonlocal是什么, 此时引入资料, 介绍 nonlocal:
7.13. The nonlocal statement
“””
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.

nonlocal 声明其罗列的标识符指向先前在最近的作用域(除了globals)
外绑定的变量的标识符. 因为默认的行为是优先绑定 local namespace
局域的命名空间, 所以 nonlocal 的出现是非常重要的. nonlocal 声明
允许封闭区域内的代码重新绑定外部的局部作用域变量(除了全局或者
模块级别的作用域之外的).

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).

nonlocal 声明的变量名字, 与全局声明的变量不同的是, 它们必须
引用自其他封闭作用域里已绑定的变量(该作用域里一个新的绑定应该
是被创建的时而不能有定义的歧义).

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

nonlocal 声明的变量名字, 在其作用域内必须不能与先前把绑定命名有冲突
(这里我的理解为命名应该是相同的).

“””

在Python3 解释器里执行 nonlocal x 语句, 抛出异常 SyntaxError,
也验证了文档说明的不能在 module 层面使用该关键字:

>>> nonlocal x
>>> File ““, line 1
>>> SyntaxError: nonlocal declaration not allowed at module level

参考:
《代码之髓》
PEP 3104 – Access to Names in Outer Scopes
the nonlocal statement – python docs

原创文章,转载请注明: 转载自kaka_ace's blog

本文链接地址: Python3 使用 nonlocal keyword 实现保存状态的嵌套函数

One thought on “Python3 使用 nonlocal keyword 实现保存状态的嵌套函数

发表评论

电子邮件地址不会被公开。 必填项已用*标注