Python 词法作用域规范 | Google 官方闭包写法
词法作用域(Lexical Scoping, 又名静态作用域)
Tip
可以使用。
定义:
嵌套的 Python 函数可以引用外层函数中定义的变量,但是不能对这些变量赋值。变量的绑定分析基于词法作用域,也就是基于静态的程序文本。任何在代码块内给标识符赋值的操作,都会让 Python 将该标识符的所有引用变成局部变量,即使读取语句写在赋值语句之前。如果有全局声明,该标识符会被视为全局变量。
一个使用这个特性的例子:
def get_adder(summand1: float) -> Callable[[float], float]:
"""返回一个函数,该函数会给一个数字加上指定的值."""
def adder(summand2: float) -> float:
return summand1 + summand2
return adder
(译者注:这个函数的用法大概是: fn = get_adder(1.2); sum = fn(3.4),结果是 sum == 4.6。)
优点:
通常会产生更清晰、更优雅的代码。尤其是让熟练使用 Lisp 和 Scheme(还有Haskell, ML等)的程序员感到舒适。
缺点:
可能引发让人困惑的 bug,例如下面这个依据 PEP-0227 改编的例子:
i = 4
def foo(x: Iterable[int]):
def bar():
print(i, end='')
# ...
# 很多其他代码
# ...
for i in x: # 啊哈, i 是 Foo 的局部变量, 所以 bar 得到的是这个变量
print(i, end='')
bar()
因此 foo([1, 2, 3]) 会输出 1 2 3 3 ,而非 1 2 3 4。
(译者注:x是一个列表,for循环其实是将x中的值依次赋给i。这样对i的赋值就隐式的发生了,整个foo函数体中的i都会被当做局部变量,包括bar()中的那个。这一点与 C++ 之类的语言还是有很大差别的。)
结论:
可以使用。