深入理解Python中命名空间的查找规则LEGB


Posted in Python onAugust 06, 2015

名字空间

Python 的名字空间是 Python 一个非常核心的内容。
其他语言中如 C 中,变量名是内存地址的别名,而在 Python 中,名字是一个字符串对象,它与他指向的对象构成一个{name:object}关联。
Python 由很多名字空间,而 LEGB 则是名字空间的一种查找规则。
作用域

Python 中name-object的关联存储在不同的作用域中,各个不同的作用域是相互独立的。而我们就在不同的作用域中搜索name-object。

举个栗子,来说明作用域是相互独立的。

In [11]: i = "G"

In [12]: def test():
      i = "L"
      print i, "in locals"
  ....:

In [13]: test()
    L in locals

In [14]: print i, "in globals"
    G in globals

 

在上面的栗子中,我们定义了两次 i,在 test 函数中是 i-L,在外面是 i-G。为什么在 test 函数中,我们 i 指向的是对象 L,而在外面,i 指向的则是 G?这就是 LEGB 的作用。
简述

简而言之,LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__

  •     locals 是函数内的名字空间,包括局部变量和形参
  •     enclosing 外部嵌套函数的名字空间(闭包中常见)
  •     globals 全局变量,函数定义所在模块的名字空间
  •     builtins 内置模块的名字空间

所以,在 Python 中检索一个变量的时候,优先回到 locals 里面来检索,检索不到的情况下会检索 enclosing ,enclosing 没有则到 globals 全局变量里面检索,最后是到 builtins 里面来检索。

当然,因为 builtins 的特殊性,我们可以直接在 builtins 里面添加变量,这样就可以在任意模块中访问变量,不过这种方法太过于变态,不推荐这么做。
locals,globals

函数的形参跟内部变量都存储在 locals 中。

In [1]: def f(x):
  ...:   a = x
  ...:   print a
  ...:   print locals()
  ...:


In [2]: f("hello")
hello
{'a': 'hello', 'x': 'hello'}

不过在函数内部调用global 声明的时候,可以将变量存储在 globals 中

In [6]: def f(x):
  ...:   global a
  ...:   a = x
  ...:   print a
  ...:   print locals()
  ...:

In [7]: f("hello")
hello
{'x': 'hello'}

In [8]: print a
hello

In [9]: print x
---------------------------------------------------------------------------
NameError                 Traceback (most recent call last)
<ipython-input-9-2d264e11d975> in <module>()
----> 1 print x

NameError: name 'x' is not defined

如上面栗子中那样,在函数中声明 a 为全局变量,则函数 f 的 locals只有参数 x,而没有变量,而在外部可以使用变量 a,而使用 x 的时候则是NameError
Enclosed

Enclosing 是外部嵌套函数的名字空间。我们经常在闭包中用到。在 Python3中提供了一个 nonlocal关键字来修改外部嵌套函数的名字空间,但是要使用 Python3才有,我等使用 Python2的只能眼馋一下。

In [11]: def outer():
  ....:   a_var = 'enclosed value'
  ....:   print a_var
  ....:   def inner():
  ....:     a_var = 'local value'
  ....:     print(a_var)
  ....:   inner()
  ....:   print a_var
  ....:

In [12]: outer()
enclosed value
local value
enclosed value

下面的栗子简单示范一下 nonlocal 的用法,实在 Python3下面才可以正常运行的:

In [1]: a_var = 'global value'

In [2]: def outer():
  ...:   a_var = "local value"
  ...:   print("outer befor", a_var)
  ...:   def inner():
  ...:     nonlocal a_var
  ...:     a_var = "inner value"
  ...:     print("in inner():", a_var)
  ...:   inner()
  ...:   print("outer inner:", a_var)
  ...:

In [3]: outer()
outer befor local value
in inner(): inner value
outer inner: inner value

In [4]: print(a_var)
global value

builtins

builtins 则是内置模块,轻易不要修改

In [19]: b
---------------------------------------------------------------------------
NameError                 Traceback (most recent call last)
<ipython-input-19-3b5d5c371295> in <module>()
----> 1 b

NameError: name 'b' is not defined

In [20]: __builtins__.b = "builtins"

In [21]: b
Out[21]: 'builtins'

上面栗子中在第一次调用b的时候报错NameError,之后我们修改 builtins 的名字空间,将名字b与值"builtins"进行关联,就可以正常调用了。这种非常规用法不建议使用。

Python 相关文章推荐
Python实现的最近最少使用算法
Jul 10 Python
使用Python的urllib和urllib2模块制作爬虫的实例教程
Jan 20 Python
python PyTorch预训练示例
Feb 11 Python
删除python pandas.DataFrame 的多重index实例
Jun 08 Python
Python 字符串转换为整形和浮点类型的方法
Jul 17 Python
python中reader的next用法
Jul 24 Python
matplotlib实现热成像图colorbar和极坐标图的方法
Dec 13 Python
pycharm创建一个python包方法图解
Apr 10 Python
Python 给屏幕打印信息加上颜色的实现方法
Apr 24 Python
Python求两点之间的直线距离(2种实现方法)
Jul 07 Python
Python 微信公众号文章爬取的示例代码
Nov 30 Python
Python用户自定义异常的实现
Dec 25 Python
举例详解Python中yield生成器的用法
Aug 05 #Python
Python中return语句用法实例分析
Aug 04 #Python
python函数形参用法实例分析
Aug 04 #Python
Python简明入门教程
Aug 04 #Python
将Python代码打包为jar软件的简单方法
Aug 04 #Python
python函数局部变量用法实例分析
Aug 04 #Python
python删除列表内容
Aug 04 #Python
You might like
人族 Terran 魔法与科技
2020/03/14 星际争霸
自定义PHP分页函数
2006/10/09 PHP
php session处理的定制
2009/03/16 PHP
php通过获取头信息判断图片类型的方法
2015/06/26 PHP
利用“多说”制作留言板、评论系统
2015/07/14 PHP
php简单实现单态设计模式的方法分析
2017/07/28 PHP
在textarea文本域中显示HTML代码的方法
2007/03/06 Javascript
用javascript动态调整iframe高度的代码
2007/04/10 Javascript
理解Javascript_10_对象模型
2010/10/16 Javascript
基于JQuery的日期联动实现代码
2011/02/24 Javascript
jQuery 1.5.1 发布,全面支持IE9 修复大量bug
2011/02/26 Javascript
基于jQuery实现的当离开页面时出现提示的实现代码
2011/06/27 Javascript
异步javascript的原理和实现技巧介绍
2012/11/08 Javascript
JavaScript学习笔记之JS事件对象
2015/01/22 Javascript
jquery图形密码实现方法
2015/03/11 Javascript
简单介绍JavaScript数据类型之隐式类型转换
2015/12/28 Javascript
bootstrap实现弹窗和拖动效果
2016/01/03 Javascript
详解vue 中使用 AJAX获取数据的方法
2017/01/18 Javascript
Bootstrap中glyphicons-halflings-regular.woff字体报404错notfound的解决方法
2017/01/19 Javascript
微信小程序chooseImage的用法(从本地相册选择图片或使用相机拍照)
2018/08/22 Javascript
代码实例ajax实现点击加载更多数据图片
2018/10/12 Javascript
vue 之 css module的使用方法
2018/12/04 Javascript
vue 动态表单开发方法案例详解
2019/12/02 Javascript
Python2.x版本中基本的中文编码问题解决
2015/10/12 Python
关于PySnooper 永远不要使用print进行调试的问题
2021/03/04 Python
css3 column实现卡片瀑布流布局的示例代码
2018/06/22 HTML / CSS
在HTML5 canvas里用卷积核进行图像处理的方法
2018/05/02 HTML / CSS
KIKO MILANO英国官网:意大利知名化妆品和护肤品品牌
2017/09/25 全球购物
英国家用电器购物网站:Hughes
2018/02/23 全球购物
新员工培训个人的自我评价
2013/10/09 职场文书
学校领导班子对照检查材料
2014/09/24 职场文书
2014年反腐倡廉工作总结
2014/12/05 职场文书
教师个人总结范文
2015/02/11 职场文书
2015年药店店长工作总结
2015/04/29 职场文书
家长会主持词开场白
2015/05/29 职场文书
关于CSS自定义属性与前端页面的主题切换问题
2022/03/21 HTML / CSS