@ghimi
2018-10-09T06:05:01.000000Z
字数 2320
阅读 1192
Python
先从几个典型的案例来看下名称空间及作用域对Python代码运行的影响,请看下面几个代码实例及其执行结果,是否符合你的预期.
if True:
i = 1
print(i)
执行结果: 1
def f():
i = 1
f()
print(i)
执行结果:执行报错NameError: name 'i' is not defined
i = 1
def test():
i += 1
test()
执行结果: 执行报错:UnboundLocalError: local variable 'i' referenced before assignment
i = 1
def g():
print(i)
def f():
i = 2
g()
f()
执行结果: 1
i = 1
def f():
i = 2
def g():
print(i)
return g
func = f()
func()
print(i)
执行结果:
2
1
PS:Python2.1之前执行该代码会报错,闭包(嵌套作用域)是在之后引入的概念,内部函数个g()执行访问本函数中的命名空间,全局命名空间,内建命名空间,无法访问外部调用函数的命名空间.
名称到对象的映.命名空间是一个字典的实现,键为变量名,值是变量对应的值.各个命名空间是独立没有关系的,一个命名空间中不能有重名,但是不同的命名空间可以重名而没有任何影响.
Python 程序执行期间会有 2 个或 3 个活动的命名空间(函数调用时有 3 个,函数调用结束后 2 个).按照变量定义的位置,可以划分为以下 3 类:
各个命名空间创建顺序: Python 解释器启动 -> 创建内建命名空间 -> 加载模块 -> 创建全局命名空间 -> 函数被调用 -> 创建局部命名空间
各个命名空间销毁顺序: 函数结束调用 -> 销毁函数对应的局部命名空间 -> Python 虚拟机(解释器)退出 -> 销毁全局命名空间 -> 销毁内建命名空间
Python解释器加载阶段会创建出内建命名空间,模块的全局命名空间,局部命名空间是在运行阶段函数被调用时动态创建出来的,函数调用结束时动态销毁的
作用域是针对变量而言,值申明的变量在程序里的可应用范围.或者成为变量的可见性.
只有函数,类,模块会产生作用域,代码块不会产生作用域(参考代码1).作用域按照变量的定义位置可以划分为4类:
* Local(函数内部)局部作用域
* Encloding(嵌套函数的外层函数内部)嵌套作用域(闭包)
* Global(模块全局) 全局作用域
* Built-in (内建)内建作用域
定义: Python 中变量的作用域是由它在源代码中的位置决定的.(名字查找是动态发生的)
说明: 参考代码3/4,以代码3为例说明,在模块中定义了一个全局变量 i = 1 , 在 test 方法中执行了 i += 1 ,对变量 i 进行了赋值动作,该赋值动作决定了 i 在 test() 方法中是一个局部变量, i += 1 可以拆分为两步执行,首先执行 i + 1 ,然后将结果赋值给 i.执行 i + 1 操作时,i 虽然申明为局部变量,但是没有绑定任何具体值,因此报错.
定义: 由一个赋值语句引进的名字在这个赋值语句所在的作用域里氏可见的(起作用),而且在其内部嵌套的每个作用域内也可见,除非它被嵌套与内部的且引进同样名字的赋值语句所遮蔽.
说明: 参考代码5. 方法g()是方法f()中定义的内嵌函数.在方法f()中定义的局部变量 i = 2,在内嵌方法 g() 中是可见的.如果在 g() 中又定义一个重名的变量 i = 3,在f()中定义的变量将被遮蔽.
命名空间定义了某个作用域内变量名和绑定值之间的对应关系,命名空间是键值对的集合,变量名与值是一一对应关系.作用域定义了命名空间中的变量能够在多大范围内起作用.
命名空间在Python解释器中是以字典的形式存在的,是以一种可以看得见摸得着的实体存在的.作用域是Python解释器定义的一种规则,该规则确定了运行时变量查找的顺序,是一种形而上虚的规定.
Python 解释器动态执行过程中,对遇到的变量进行解释时,是按照一条固定的作用域链查找解释的,又称为LEGB法则.
其中L代表Local 局部作用域,E代表Enclosing嵌套作用域,G代表 Global全局作用域,B代表 Built-in 内建作用域
Python 解释器查找变量时,会按照顺序依次查找局部作用域,嵌套作用域,全局作用域,内建作用域,在任意一个作用域中找到变量则停止查找,所有作用域查找完成没有找到对应的变量,则抛出
NameError: name 'xxx' is not defined的异常
在局部作用域中,可以看到局部作用域,嵌套作用域,全局作用域,内建作用域中所有定义的变量.
在全局作用域中,可以看到全局作用域,内建作用域中所有定义的变量,无法看到局部作用域中的变量.