Notes on Python Naming and binding

来源:互联网 发布:gcc linux 安装 编辑:程序博客网 时间:2024/06/06 03:18

在看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。

 

执行结果:

Inside the function var is bar

Outside the function var is bar

但是global解决不了“access to names in outer scopes",比如下面的例子:

 

执行结果为:

 

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的例子:

 

结果是:

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,除了文档里面的例子外,我们可以看下面的例子:

 

 

运行时会报错:NameError: global name 'var7' is not defined,说明访问var7出错了,这跟Java很不一样,在上面的例子中,如果我们希望访问var7,必须加上self.前缀。

 

 

原创粉丝点击