Python学习笔记:作用域和命名空间

本篇参考官方文档: The Python Tutorial 9.2: Python Scopes and Namespaces

这节非常重要,许多错误都是对作用域和命名空间不熟悉导致的。先看看文档里对命名空间(namespace)的定义:

命名空间是从名字到对象的映射。大多数命名空间目前是由Python字典实现的。例子有:内建(built-in)名字(比如abs()函数);一个模块里的全局名字,一个函数里的本地名字。某种意义上对象的属性(attribute)也形成了命名空间。不同命名空间里的名字之间没有关系;比如,两个不同的模块可能都定义了函数maximize而不产生困扰—模块的用户必须加上模块名前缀。

名字和对象也是非常重要的概念,参考Python学习笔记:对象,值和类型。简而言之名字是变量的标识符,也是引用。任何尾随点(.)的名字都叫做属性。比如,在z.real中,real是对象z的一个属性。attribute作动词还有“归属”,“把…归于”的意思,所以把尾随点(.)的名字都叫做属性是很合理的。命名空间的概念源自编译原理的符号表(symbol table)

接下来讲命名空间的创建和删除:

命名空间可以在不同的时刻创建,而且有不同的寿命。包含内建名字的命名空间在Python解释器启动一开始就创建了,永不被删除。一个模块的全局命名空间在模块被读进的时候创建,通常也持续到解释器停止。
一个函数的本地命名空间在函数被调用的时候创建,函数返回或抛出异常的时候删除。


接下来该说作用域了:

一个作用域是一个Python程序的文本区域(textual region),在这里一个命名空间是直接可访问的(directly accessible)。“直接可访问”的意思是一个未经限定(unqualified)的变量引用试图在命名空间里寻找这个变量。

这段就比较费解了,有很多莫名其妙的词。文本区域指的是程序代码中的某一块,作用域规定了在这一文本区域哪些命名空间会发生作用。打个比方,作用域就是一个县规章制度,它规定了所辖各个镇的居民的名字和电话号的对应关系。比如你是牵牛乡的,想查小红的电话号,作用域会甩给你牵牛乡的电话本。如果你想查红旗镇的小红的电话号,不好意思,不可以。

虽然作用域被全局地确定,但是被动态地使用。在程序执行的任何时间,至少有三种嵌套的作用域,它们的命名空间是直接可访问的:
- 最里面那层的作用域,被最先搜索,它包含了本地名字。
- 封闭(enclosing)函数的作用域,从最近的(nearest)封闭作用域开始搜索,包含了非本地、非全局地名字。
- 倒数第二的作用域包含了当前模块的全局名字。
- 最外层的作用域(最后搜索) 是内建名字的命名空间。

作用域又可理解成权限,一块代码对哪些命名空间有权限。封闭函数是内部有至少另一个函数定义的函数,跟Java的内部类有点像。

如果一个名字被声明成global,那么所有的引用和赋值都直接在中层的包含此模块的全局名字的作用域发生。否则,所有在最里层作用域之外发现的变量都是只读的(写这种变量仅仅会在最里层作用域创建一个新的本地变量)。
同常,本地作用域联系着当前函数的本地变量。在函数之外,本地作用域就联系着跟全局作用域相同的命名空间了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值