
在 python 中,变量查找遵循 LGB 原则,即优先在局部作用域 (local scope)中对变量进行查找,
失败则在全局作用域 (global scope)中进行查找 ,最后尝试再内建作用域 (build-in scope)内查
找,如果还是未找到的话,则抛出异常。 后来由于闭包和嵌套函数的出现, 作用域又增加了
外部作用域, 这样变量的查找作用域优先级变为: 局部、外部、 全局和内建。 作用域由 def、
class、lambda 等语句产生, if 、try 、for 等语句并不会产生新的作用域。变量名引用分为三
个作用域进行查找:首先是本地,然后是函数内(如果有的话) ,之后是全局,最后是内置。
在默认情况下, 变量名赋值会创建或者改变本地变量。 全局声明将会给映射到模块文件内部
的作用域的变量名赋值。 Python 的变量名解析机制也称为 LEGB 法则, 具体如下: 当在函
数中使用未确定的变量名时, Python 搜索 4 个作用域:本地作用域( L),之后是上一层嵌
套结构中 def 或 lambda 的本地作用域( E),之后是全局作用域( G),最后是内置作用域
(B)。按这个查找原则,在第一处找到的地方停止。如果没有找到, Python 会报错的。
[python]
1. a = 1
2. def f():
3. a = 2
4. def g():
5. print a //[1] :输出结果为 2
6. return g
7. func = f()
8. func()//[2]
代码的 [2] 处调用的函数实际上调用的是函数 f 中定义的内嵌函数 g,在代码 的[1] 处,
函数 g 内的 “print a ”的输出结果为 2。初看上去有些疑问,因为函数 f 内的约束 “a = 2 ”在其
之外应该是不起作用的,当执行 func() 时,起作用的约束应该是 “a = 1 ”才对。但是我们之前
说到了,作用域仅仅是由文本决定的,函数 g 位于函数 f 之内,所以函数 g 定义的作用域
内嵌于函数 f 的作用域之内。换句话说,函数 f 的作用域是函数 g 的作用域的直接外围作
用域,所以,按照最内嵌套作用域规则, [1] 处的名字引用应该引用的是函数 f 定义的作用
域中所创建的约束。
尽管在代码清单 8-2 的[2] 处,“a = 2 ”这个约束已经不起作用了,但是 Python 在执行 “func =
f() ”时,会执行函数 f 中的 “ def g(): ”语句,这时 Python 会将约束 “ a = 2”与函数 g 对应的函
数对象捆绑在一起,将捆绑后的结果返回,这个捆绑起来的整体被称为 “闭包 ”。
实际上这里有一个相当微妙的问题,最内嵌套作用域规则是 “闭包 ”的结果呢,还是 “闭
包”是最内嵌套作用域规则的实现方案?这两个问题看上去是一致的,但却隐含着谁决定谁
的关系。实际上, Python 实现闭包是为了实现最内嵌套作用域规则。换句话说,最内嵌套
作用域规则是语言设计时的设计策略, 即是形而上的 “道”;而闭包则实现语言时的一种方案,
即是形而下的 “器”。
[python]
1. python 能够改变变量作用域的代码段是 def、class、lamda.