Python3.x那些事儿:[63]作用域和命名空间

2025-10-23 21:41:27

命名空间是从名字到对象的一组映射。大部分的命名空间目前都是使用Python的字典类型来实现的,但是并没有进行规定(除非是为了性能考虑),这种情况可能会在将来有所改变。例如:内置名称的集合(包含函数和内置异常类型);一个模块中的全局名称;一个函数调用过程中的本地名称。从某种意义上来说一个对象中的所有属性的集合也构成一个命名空间。在命名空间中需要知道的一个重要事实是在不同的命名空间中名字之间是没有任何关系的,例如,两个不同的模块都定义了一个函数maximize,但是它们并不会发生冲突。

同时,任何一个.后面跟着的名称都被称为属性,例如,在z.real表达式中,real是对象z的一个属性。严格来说,对模块中名字的引用都是属性引用,在表达式modname.funcname中,modname是一个模块对象,funcname是它的一个属性。在这里刚好有一个模块属性与模块中全局名字的映射,因此它们使用的是同一个命名空间。有一件事情是个例外,模块对象中有一个秘密的只读属性叫做__dict__,它返回一个字典类型用来实现模块中的命名空间。__dict__是一个属性但是不是一个全局名称。显然,使用这个东西违反了命名空间实现的抽象性原则,因此要严格控制使用,只有在某些调试器中可以使用。

属性可以使只读或者是可写的。在可写情况下,给属性赋值是可以的。模块属性都是可写的。你可以写:modname.the_answer=42。可写属性也可以使用del语句删掉。例如,del modname.the_answer会删除modname模块中的the_answer属性。

命名空间会在不同的时间创建,并有不同的生命周期。包含内置名称的命名空间是在python解释器启动的时候创建的,并且不会被删除。一个模块的全局命名空间是在模块定义代码被读入的时候创建的,一般情况下,模块命名空间会持续到解释器结束。在解释器最上层调用的代码,不管是从脚本中读入的还是在交互式界面中,都会被认为是属于一个叫做__main__模块的,所以它们有自己的全局命名空间。(内置名称实际上也放置在一个模块中,称为builtins)。

函数的本地命名空间会在函数被调用的时候被创建,当函数返回或者是出现异常并且没有被函数处理的时候被删除。当然递归调用的每一次调用都会产生一个独立的本地命名空间。

作用域是一个Python程序中命名空间能够直接接触到的部分。也就是说直接用名字进行引用就可以使用的命名空间。

虽然作用域是静态确定的,实际上他们是动态的。运行时的任何时间,都会存在三个嵌套的作用域:

1、最内层作用域,会被最先查找,包含本地名称。

2、函数作用域,包含非本地,但是也非全局的名称。

3、包含模块全局名称的作用域。

4、最外层的作用域,包含内置名称。

如果一个名称被声明为global,那么所有的引用和赋值都会直接作用于模块全局名称。为了将一个外部变量重新绑定到外部,则可以使用nonlocal关键字。如果没有声明nonlocal,这些变量就是只读的(试图去写一个这样一个变量会在内层作用域中重新创建一个新的本地变量)。

通常,本地作用域会引用当前函数的本地变量。

(共篇)上一篇:名字和对象|下一篇:
声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢