Python 之作用域和名字空间
作用域与名字空间
Python有一个核心概念是名字空间(namespace),namespace是一个name到object 的映射关系,Python有很多namespace,因此,在代码中如果碰到一个标志符(name),需要有一个规则来决定去哪个namespace查找——这就是LEGB。
LEGB决定了name的查找顺序:locals -> enclosing function -> globals -> __builtins__
- locals 是函数内的名字空间,包括局部变量和形参;
- enclosing 外部嵌套函数的名字空间(闭包中常见);
- globals 全局变量,函数定义所在模块的名字空间;
- builtins 内置模块的名字空间;
所以,在 Python 中检索一个变量的时候,优先到 locals 里面来检索,检索不到的情况下会检索 enclosing ,enclosing 没有则到 globals 全局变量里面检索,最后是到 builtins 里面来检索。
当然,因为 builtins 的特殊性,我们可以直接在 builtins 里面添加变量,这样就可以在任意模块中访问变量,不过这种方法太过于变态,不推荐这么做。
LGB规则(闭包是一种特殊的作用域,暂不考虑)与name space加载的顺序相反,Python解释器初始化的时候会先加载built-in namespace,它由__builtins__模块的名字构成,随后加载global namespace。 如果在执行期间调用了一个函数,那么将创建局部名字空间。
Python中一切都是object,包括function、module、class、package,这些objects都有在内存中真真正正的存在。每个object都有自己的namespace,每个object的namespace是独立的,可以通过object.name的方式访问object的namespace中的name,因此,不同的namespace中可以使用相同的name,而不会引发混淆。namespace是动态创建的,每一个namespace的生存时间也不一样。例如,一个module的namespace是它被import的时候创建的。而function被调用时,创建其local namespace,调用结束或抛出exception的时候, 该local namespace将被删除。
locals( )和globals( )分别返回dictionary结构的global namespace和local namespace,例如:
a = 3 def proc():
a = 3
print(locals())
print(globals()) proc()
可以看见,局部作用域和全局作用域都有变量a,但它们不是同一个对象。
注意:还有一个特殊的module,一进入python解释器,就建立了一个module,这个module的namespace就是global namespace,一个全局唯一的namespace。这个module的一个内部的attribute,__name__等于__main__。如果模块是被导入的,__name__的值为模块的名字;如果模块是被直接执行的,__name__的值为’__main__’。
scope(作用域):用unqualified reference name(即与object.name相比,没有object的前缀)就可以直接找到name所指的对象。 LGB规则用scope的概念来解释就是:在任何代码执行的时候,都至少有3个scope,从内到外一次查找一个unqualified reference name。
函数体内的局部变量和全局变量如果重名,全局变量不可见(被局部变量覆盖)。
x = 50 def func(x):
print('x=', x) #
x = 2
print('x=', x) # func(x) print('x=', x) #
一个更复杂的例子:
j, k = 1, 2 def proc1():
j, k = 3, 4
print "j==%d and k=%d" %(j,k)
k = 5 def proc2():
j = 6
proc1()
print "j==%d and k=%d" %(j,k) k = 7
proc1()
print "j==%d and k=%d" %(j,k) j = 8
proc2()
print "j==%d and k=%d" %(j,k)
当在函数中需要修改全局变量时,如果没有global关键字则会出错:
x = 50 def run():
print x
x = 2 run()
报错为:UnboundLocalError: local variable 'x' referenced before assignment
加上global关键字以后则OK
x = 50 def run():
global x
x = 2 run()
print x #
Python 之作用域和名字空间的更多相关文章
- python tips:作用域与名字空间
Python具有静态作用域,变量的作用域由它定义的位置决定,而与调用的位置无关. a = 2 def f(): a = 2 第一行的a的作用域是全局作用域,作用于定义位置后面的所有位置. 第四行的a的 ...
- C和C++中的名字空间和作用域
C和C++中的名字空间和作用域 C语言中有名字空间这个概念吗? 提到名字空间(或者可能更普遍的叫法,命名空间),很可能先想到的是C++,甚至是C#.C中没有名字空间吧?一开始我也是这样认为的,直到我看 ...
- C++笔记--名字空间和异常
名字空间 成员函数可以在名字空间的定义里去声明,然后再去采用一种定义方式例如:namespace__name::member_name的方式去定义这个成员函数 namespace parser{ do ...
- python中的作用域与名称空间
python中的名称空间以及作用域分析 从Python解释器开始执行之后,就在内存中开辟一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征 ...
- Python虚拟机函数机制之名字空间(二)
函数执行时的名字空间 在Python虚拟机函数机制之无参调用(一)这一章中,我们对Python中的函数调用机制有个大概的了解,在此基础上,我们再来看一些细节上的问题.在执行MAKE_FUNCTION指 ...
- Python 3里,reduce()函数已经被从全局名字空间里移除了,它现在被放置在fucntools模块里
reduce函数:在Python 3里,reduce()函数已经被从全局名字空间里移除了,它现在被放置在fucntools模块里 用的话要 先引入:>>> from functool ...
- Python全栈之路----函数进阶----作用域的查找空间
n = 10 def func(): n = 20 print('func:',n) def func2(): n = 30 print('func2:',n) def func3(): print( ...
- python函数作用域
python中函数作用域 在python中,一个函数就是一个作用域 name = 'xiaoyafei' def change_name(): name = '肖亚飞' print('在change_ ...
- Python 变量作用域 LEGB (上)—— Local,Global,Builtin
Python 变量作用域的规则是 LEGB LEGB含义解释:L —— Local(function):函数内的名字空间E —— Enclosing function locals:外部嵌套函数的名字 ...
随机推荐
- 引入AOP 报错 error at ::0 formal unbound in pointcut
使用了AOP 后启动报错 九月 27, 2016 2:29:46 下午 org.springframework.context.support.AbstractApplicationContext r ...
- OPENGL若干重要基础概念
投影:3D数据“压平”到2D的计算机屏幕上,即将真正的三维物体显示到二维屏幕上,这种3D压平到2D的过程称为投影. 投影类型:正投影,透视投影 正投影:垂直于投影平面的平行投影(不垂直的投影平面的平行 ...
- 【BZOJ-3165】Segment 李超线段树(标记永久化)
3165: [Heoi2013]Segment Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 368 Solved: 148[Submit][Sta ...
- 验证时出错。HRESULT = '8000000A'
往往出现在 做了安装项目后有警告: 解决办法: 这本来是在VS2005下创建的一下项目,后来改用VS2010的开发环境,.NET Framework的版本还是使用2.0, 但每次生成之后都会在解决方案 ...
- mysql导出表数据
mysqldump -upcrm -ppcrmUser*1 -h192.168.01.01 -P3399 ecrm_order0 T_EOrder>bak.sql MYSQLdump参数详解 m ...
- 关于Unity3d粒子系统的小发现(天堂3技能释放)
导入系统给的粒子包,发现了一个问题:系统的粒子都有移动轨迹. 而自己新建的空粒子系统却没有这个功能.顺便也复习一下粒子系统. Particle System (粒子系统): Duration(持续时间 ...
- InternalsVisibleToAttribute——把internal成员暴露给指定的友元程序集
友元程序集简介 我们知道一个类中被定义为internal的成员(包括类型.方法.属性.变量.事件)是只能在同一个程序集中被访问到的(当然了,我这里说的是正常的方式,不包括通过反射来访问).这个规则在. ...
- XmlReader读取XML
StringBuilder output = new StringBuilder(); String xmlString = @"<bookstore> <book gen ...
- 在CentOS上安装Sublime Text
CentOS 是基于 Red Hat (RHEL) 的, 其中并没有包管理工具 apt. 最近需要在装了 CentOS 系统的服务器上安装Sublime Text, 到官网上看了一下, 对其他 (De ...
- Linux下安装py-leveldb
1.下载源代码 svn checkout http://py-leveldb.googlecode.com/svn/trunk/ py-leveldb-read-only 2.安装辅助工具 sudo ...