8.2.3 作用域与名字空间
在8.2.2 节中,我们提到,约束一旦被创建,就会被放入名字空间中,然后影响程序的行为。在module 内部,这样的描述是没错的,但是还不够细致。在module 内部,名字空间存在着一个可见性的问题。我们来考虑下面的例子(见代码清单8-1)。
代码清单8-1
[B.py] |
在代码清单8-1 的[3]处的输出结果为2, [4]处的输出结果为1,这个结果意味着在代码清单8-1 的[1]和[2]处的两个赋值语句是在不同的名字空间中创建了约束,而[3]和[4]处的“print a”也使用了不同的名字空间中的名字“a”。
在一个module 内部,可能存在多个名字空间,每一个名字空间都与一个作用域对应。一个约束起作用的那一段程序正文区域称为这个约束的作用域。而一个作用域则是指一段程序正文区域,在这个区域里,可能有很多个约束在起作用,一旦出了这个正文区域,这些约束都不起作用了。在B.py 中,第3 行和第4 行程序正文就组成了一个作用域,在这个作用域中,“a = 2”这个约束起作用,从而影响代码清单8-1 的[3]处的输出;“a = 2”这个约束不能影响[4]的输出,因为第5 行代码不在函数f 所定义的作用域之内,所以“a =2”这个约束不起作用。
对于作用域这个概念,至关重要的是要记住它仅仅是由源程序的文本决定的。在Python 中,一个约束在程序正文的某个位置是否起作用,是由该约束在文本中的位置是否唯一决定的,而不是在运行时动态决定的。因此,Python 是具有静态作用域(也称词法作用域)的。而名字空间就是与作用域对应的动态的东西,一个由程序文本定义的作用域在Python 程序运行时就会转化为一个名字空间,一个内存中的PyDictObject 对象。也就是说,在函数f 执行时,Python 会为f 创建一个名字空间,这一点在以后剖析函数机制时会详细介绍。
位于一个作用域中的代码可以直接访问作用域中出现的名字,所谓“直接访问”,就是指不用加上属性引用方式的访问修饰符“.”:比如在B.py 中访问A.py 中的名字a,需要使用“print A.a”的方式;而在B.py 中访问自己这个module 中的名字a,则直接使用“print a”这样的方式就可以了。
访问名字这样的行为被称为名字引用,名字引用的规则决定了Python 程序的行为。还是考虑B.py,如果我们删除第3 行代码,那么第4 行代码的输出结果会如何呢?我们已经知道,赋值语句实际上创建了约束,删除第3 行代码,意味着在函数f 定义的作用域中,没有了与名字a 相对应的约束。换句话说,在调用函数f 时,名字空间中没有名字a 了。那么“print a”的行为该如何定义呢?
一种方案是抛出异常,显然,这是非常糟糕的方案;而另一种方案是使用当前作用域(函数f 定义的作用域)之外的名字a,那么输出的结果就该为1。Python 选择了第二种方案,也就是说,Python 支持嵌套作用域。
前面我们提到,module 本身关联着一个名字空间,所以module 对应的程序正文,即B.py 自身就是一个作用域,而B.py 中的函数f 定义的作用域位于B.py 定义的作用域之内,这样的情况,就称为嵌套作用域。Python 的名字引用的行为被它所支持的嵌套作用域影响,产生的就是最内嵌套作用域规则:由一个赋值语句引进的名字在这个赋值语句所在的作用域里是可见(起作用)的,而且在其内部嵌套的每个作用域里也可见,除非它被嵌套于内部的,引进同样名字的另一条赋值语句所遮蔽。
为了找到某个给定名字所引用的对象,应该用这个名字在当前的作用域(名字空间)里查找。如果在这里找到了对应的约束,它就是与这个名字相关的活动约束。否则,就应该到直接的外围作用域(名字空间)去查找,并继续向外顺序地检查外围作用域(名字空间),直到到达程序的最外嵌套层次。这个最外嵌套层次就是module 自身所定义的那个作用域。
| 回书目 |
|
||||
| · 无线路由器故障处理 · 解析35岁技术人的价值.. · 无线重中之重:安全问题 · 无线局域网基本知识 · 家庭无线局域网 · 华为七千人主动辞职规.. · 微软出价446亿美元收购.. · 虚拟化的“赤壁之战” |
· Windows Server 2008专.. · 802.11n:下一代的无线.. · 脉冲无线电uwb专题 · AIX操作系统管理应用 · 云计算时代来临 · 求职必杀技 决战面试官 · 龙芯要做中国的“奔腾” · 2008年上半年IT技术图.. |
|||
|
||||
| · SOA 面向服务架构 · SQL Server 2008/2005.. · Apache技术专题 · 三层交换技术专题 · SQL Server入门到精通 · 无线网状网(MESH) · Windows远程桌面应用 · C#技术开发指南 |
· Apache技术专题 · Windows集群服务应用 · C#技术开发指南 · 文档格式标准开战 OOXM.. · 路由器设置与口令恢复 · Linux 集群技术专题 · PHP开发应用手册 · SOA 面向服务架构 |
|||
|
||||
| · SQL Server入门到精通 · SQL Server 2008/2005.. · SOA 面向服务架构 · Apache技术专题 · C#技术开发指南 · 三层交换技术专题 · Apache技术专题 · C#技术开发指南 |
· Windows远程桌面应用 · 企业数据恢复指南 · Windows集群服务应用 · 路由器设置与口令恢复 · Linux 集群技术专题 · SOA 面向服务架构 · 了解统一威胁管理(UTM).. · 解析35岁技术人的价值.. |
|||