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:外部嵌套函数的名字 ...
 
随机推荐
- Maven-pom.xml详解
			
(看的比较累,可以直接看最后面有针对整个pom.xml的注解) pom的作用 pom作为项目对象模型.通过xml表示maven项目,使用pom.xml来实现.主要描述了项目:包括配置文件:开发者需要遵 ...
 - HTTP之referer(网上搜集)
			
1.打开httpfox抓包插件,在百度中搜索126.com,搜索项中点击网站入口,通过抓包工具,查看http请求 在http请求的Headers部分可见Referer. Referer http:// ...
 - 将代码托管到OSChina服务器上
			
前言:前面的文章已经介绍过了如何将代码托管到github的服务器.并且笔者也详细的介绍了使用HTTPS和SSH两种不同的身份验证方式.但是仅仅介绍github的使用是不够的,原因笔者已经在前面的文章中 ...
 - 【BZOJ-1552&3506】robotic sort&排序机械臂      Splay
			
1552: [Cerc2007]robotic sort Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 806 Solved: 329[Submit][ ...
 - 【BZOJ-4289】Tax      最短路 + 技巧建图
			
4289: PA2012 Tax Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 168 Solved: 69[Submit][Status][Dis ...
 - 【BZOJ-2251】外星联络    后缀数组 + 暴力
			
2251: [2010Beijing Wc]外星联络 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 670 Solved: 392[Submit][ ...
 - sbin/hadoop-daemon.sh: line 165: /tmp/hadoop-hxsyl-journalnode.pid: Permission denied
			
原来在logs下 该权限,还是不行,以root登陆可以了,但是其他节点是普通用户啊,还会出其他问题,仔细看是/tmp,就是linux根目录下的tmp,改他的权限吧,不知道重启会不会变化.
 - Capture
			
1.导出Logical symbol 单个元件导出放入指定库:左键选中元件→右键“Edit Parts”→View“Package”→file“Save As”→找到要存放的库. 从某个已经设计好的原 ...
 - Swift&Node 使用Alamofire进行Post
			
这篇博客主要实现Swift客户端和NodeJS后台的Post.Get请求实现. 我是一个略有点讨厌重复使用工具的人,比如这些基本功能完全可以用OC和PHP等替代,但是没办法,现在知识更新的太快啦,Sw ...
 - java里面时间差比较
			
currentTime.before(this.getLastActivateTime(time))//返回true 或者false public Date getLastActivateTime(t ...