在看Python Language Reference的第四章Execution model的第一节4.1 Naming and binding时,看了好几遍才明白,特意整理一下,以供参考。
首先明确两个概念:global和nonlocal(Python 3才引入,我用的版本是3.2a3)
The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals. It would be impossible to assign to a global variable without global, although free variables may refer to globals without being declared global.
简单地说,global关键字使得一个variable拥有module scope,所以有时候也叫module-global scope。
var = 'foo' def ex3(): global var var = 'bar' print('Inside the function var is {0}'.format(var)) ex3() print('Outside the function var is {0}'.format(var))
执行结果:
Inside the function var is bar
Outside the function var is bar
但是global解决不了“access to names in outer scopes",比如下面的例子:
def ex6(): var6 = 'foo' def inner(): global var6 var6 = 'bar' print("inside inner, var6 is {0}".format(var6)) inner() print("Inside outer function, var6 is {0}".format(var6)) ex6()
执行结果为:
inside inner, var6 is bar
Inside outer function, var6 is foo
这也正是Python3引入nonlocal的原因,nonlocal关键字赋予了访问外一层scope里name的能力,比如把上面例子中的global替换成nonlocal,结果就变成了:
inside inner, var6 is bar
Inside outer function, var6 is bar
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 namesapce first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.
Names listed in a nonlocal statement, unlike to 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引入的背景,可以看PEP 3104(类似于Java里的JSR):http://www.python.org/dev/peps/pep-3104/
如果你还在用Python2,你可以使用一些变通的方法达到nonlocal的效果:http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/
下面是一个综合使用nonlocal和global的例子:
def scope_test(): def do_local(): spam = "local spam" def do_nonlocal(): nonlocal spam spam = "nonlocal spam" def do_global(): global spam spam = "global spam" spam = "test spam" do_local() print("After local assignment:", spam) do_nonlocal() print("After nonlocal assignment:", spam) do_global() print("After global assignment:", spam) scope_test() print("In global scope:", spam)
结果是:
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
讲到scope的时候,特别要注意的是在class block里面定义的name的scope,它不包含类里面的方法——包括comprehensions和generator expression,除了文档里面的例子外,我们可以看下面的例子:
class cls7(): var7 = 'abc' def hello(self): print("Hello, I am " + var7) cc = cls7() cc.hello()
运行时会报错:NameError: global name 'var7' is not defined,说明访问var7出错了,这跟Java很不一样,在上面的例子中,如果我们希望访问var7,必须加上self.前缀。