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:外部嵌套函数的名字 ...
随机推荐
- Eclipse SVN插件与TortoiseSVN的对应关系及下载链接
Eclipse SVN 插件与TortoiseSVN对应关系 Eclipse 3.2/Callisto, 3.3/Europa, 3.4/Ganymede, 3.5/Galileo, 3.6/Heli ...
- jsp 中的js 与 jstl 运行的先后顺序
在jsp 中运行下面的代码,结论是:js 中可以使用 标签,js 的注释 对标签无效-- 有知道原理的吗<c:set var="flag" value="false ...
- windows-msconfig
弹出输入框,输入命令msconfig 打开系统配置,查看相关引导信息,关闭开机启动等
- ps制作gif图片
本文自学内容来自这里 PS版本是CS6: 制作效果 步骤 1.下载素材 2.打开ps,添加素材 文件->打开->选择所有需要的素材全部打开(如图,已将需要的3个素材全部打开) 3.将素材放 ...
- C# 后台json转换成时间格式
1传入json 字符进行转换 public DateTime ConvertTime(string milliTime) { long timeTri ...
- 【USACO 1.4】Arithmetic Progressions
/* TASK: ariprog LANG:C++ URL:http://train.usaco.org/usacoprob2?a=PA9lOcZrdWq&S=ariprog SOLVE:平方 ...
- ajax文件下载
今天想做一个csv导出,想做ajax下载 JQuery的ajax函数的返回类型只有xml.text.json.html等类型,没有“流”类型,所以要实现ajax下载,不能够使用相应的ajax函数进行文 ...
- hadoop 2.x 完全分布式搭建
HDFS HA 集群搭建: DN(DataNode):3个:NN(NameNode):2:ZK(ZooKeeper):3(大于1的奇数个):ZKFC:和NN在同一台机器:JN:3:RM(Resourc ...
- POJ 2484 A Funny Game(博弈论)
题目链接: 传送门 A Funny Game Time Limit: 1000MS Memory Limit: 10000K Description Alice and Bob decide ...
- CF 701B Cells Not Under Attack(想法题)
题目链接: 传送门 Cells Not Under Attack time limit per test:2 second memory limit per test:256 megabyte ...