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:外部嵌套函数的名字 ...
随机推荐
- Ext-设置form表单不可编辑
1. var formEach = win.down('form').items.items; Ext.each(formEach,function(item){ console.log(item); ...
- C#-WinForm-打开其他窗体的三种方式-Show()、设置Owner()、ShowDialog()
打开其他窗体的三种方式 Show - 例如登入界面进入主页面,直接将主页面展示出来,两个窗体互不影响 public partial class Form1 : Form { public Form1( ...
- Java数组操作利器:Arrays工具类
java.util.Arrays提供大量的工具方法来操作数组,这些方法全是静态方法. 1 便捷创建List public static <T> List<T> asList(T ...
- linux命令语法格式
一.命令的一般格式 command [option]... [argument]... command [options] [arguments] 具体说明: 1.command: 表示命令的名称,如 ...
- Bzoj2007 [Noi2010]海拔
Time Limit: 20 Sec Memory Limit: 552 MB Submit: 2380 Solved: 1130 Description YT市是一个规划良好的城市,城市被东西向 ...
- How to Prevent Cross-Site Scripting Attacks
How to Prevent Cross-Site Scripting Attacks Reference From: http://resources.infosecinstitute.com/ho ...
- c/c++中#和##链接符号的用法
#include <stdio.h> #include <stdlib.h> /* 英语原文: In function-like macros, a # operator be ...
- Node 连接Mysql并进行增删改查
NPM: NPM的全称是Node Package Manager,类似于ruby的gem,Python的PyPL.setuptools,PHP的pear,是Nodejs中的包管理器.Nodejs自身提 ...
- InteropBitmap指定内存,绑定WPF的Imag控件时刷新问题。
1.InteropBitmap指定内存,绑定WPF的Imag控件的Source属性 创建InteropBitmap的时候,像素的格式必须为PixelFormats.Bgr32, 如果不是的话在绑定到I ...
- 【Beta版本】冲刺-Day6
队伍:606notconnected 会议时间:12月14日 目录 一.行与思 二.站立式会议图片 三.燃尽图 四.代码Check-in 一.行与思 张斯巍(433) 今日进展:修改界面规范,应用图标 ...