Python Namespace


命名空间
命名空间 namespace 对 python 来说是一个非常核心的概念,整个 python 虚拟机运行的机制与 namespace 概念有这非常紧密的联系.
从'赋值'说起, python 中的赋值语句是一类特殊的语句,原因是因为它们会影响 namespace.
python 中的赋值语句首先创建一个 对象 object,然后将 obj '赋值' 给一个名字 name (理解为赋值给一个变量)
赋值语句执行后, 我们的一个 name 和 object 的关联关系, 称之为'约束', 而'约束'的容身之地就是 '命名空间'.
在 python 中, 命名空间是通过一个 PyDictObject 对象实现的。
以'类'为例, class A(object): 属于'赋值' 语句, 可以通过 A.__dict__ 查看 A 的 namespace.

看个例子,
 1 a = 1
 2         def func():
 3             a = 3
 4             print('Func -> a = ',a)   #1
 5 
 6         print('Outer -> a = ',a)      #2
 7         func()
 8         print('Outer -> a = ',a)
 9 
10         Output,
11             Outer -> a =  1       #2  #1 跟 #2 的不同结果表明, 两处的赋值语句是在不同的 namespace 中创建的'约束'
12             Func -> a =  3        #1
13             Outer -> a =  1       #   外层的 变量 a 的值并没有受到 #1 处赋值语句 a = 3 的影响.

    在一个 python 模块 module 内部, 可能存在多个 namespace, 而每一个 namespace 都与一个’作用域‘对应(一个’约束‘起作用的区域 - 即一段代码'块儿',称之为这个约束的作用域).
在上例中, def func():代码块儿就组建了一块儿作用域, 在这个作用域中 约束 'a = 3' 便起作用. 然而, 在函数定义语句 def 的'外层’是另一个作用域, 约束 ‘a = 1’ 起作用.
 
    
    现在, 将 def func():中的赋值语句 'a = 3' 注释掉, 看一下儿输出,
        Output of #a =3,
            Outer -> a =  1
            Func -> a =  1
            Outer -> a =  1

   可以看到, python 虚拟机向'外层作用域'的 namespace 中去搜索 a 的 约束 'a = 1', python 支持 '嵌套作用域'.

   为了找到某个给定 name 所引用的对象, 应该用这个 name 在当前所属的 namespace 中查找. 若找到, 它就是与这个给定 name 相关的约束。
否则, 继续向外层 namespace 中查到, 并继续依次向外层检查外层作用域直到最外层嵌套作用域。
   若还是没有找到 name 相对应的约束,则 raise exception -> ‘NameError: name 'name' is not defined’
    
原文地址:https://www.cnblogs.com/zzyzz/p/7506122.html