a = 1 def f(): a = 2 def g(): print a //[1]:输出结果为2 return g func = f() 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能够改变变量作用域的代码段是def、class、lamda. def scopetest(): localvar=6; print(localvar) scopetest() #print(localvar) #去除注释这里会报错,因为localvar是本地变量 if/elif/else、try/except/finally、for/while while True: newvar=8 print(newvar) break; print(newvar) try: newlocal=7 raise Exception except: print(newlocal)#可以直接使用哦 输出结果:8 8 7 可见这个关键字中定义变量,他们的作用域跟外部是一致的,这个跟Java的作用域概念有点不一样。 变量搜索路径是:本地变量->全局变量 def scopetest(): var=6; print(var)# var=5 print(var) scopetest() print(var) 输出结果:5 6 5 这里var 首先搜索的是本地变量,scopetest()中 var=6相当于自己定义了一个局部变量,赋值为6. 当然如果的确要修改全局变量的值,则需要如下: def scopetest(): global var var=6; print(var)# var=5 print(var) scopetest() print(var) 输出结果:5 6 6 再看一种这种情况: def scopetest(): var=6; print(var)# def innerFunc(): print(var)#look here innerFunc() var=5 print(var) scopetest() print(var) 输出结果:5 6 6 5