解读Python编程中的命名空间与作用域


Posted in Python onOctober 16, 2015

变量是拥有匹配对象的名字(标识符)。命名空间是一个包含了变量名称们(键)和它们各自相应的对象们(值)的字典。
一个Python表达式可以访问局部命名空间和全局命名空间里的变量。如果一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量。
每个函数都有自己的命名空间。类的方法的作用域规则和通常函数的一样。
Python会智能地猜测一个变量是局部的还是全局的,它假设任何在函数内赋值的变量都是局部的。
因此,如果要给全局变量在一个函数里赋值,必须使用global语句。
global VarName的表达式会告诉Python, VarName是一个全局变量,这样Python就不会在局部命名空间里寻找这个变量了。

命名空间的定义
Python命名空间是名称到对象的映射,这就像是字典,键名是变量名,值是变量的值。比如:

>>> x = 3
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'x': 3, '__package__': None}

可以看到变量x,3以字典的形式存放在globals空间内。以之对应的名字空间还有:locals()。

>>> locals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'x': 3, '__package__': None}

实际上,你可以通过向名字添加键名和值:

>>> globals()['y'] = 5
>>> y
5

上图左侧是内置命名空间,右侧是不同的模块,有各自的全局命名空间,全局命名空间内定义函数就会有局部命名空间。

命名空间的种类
Python中有三种命名空间:

a) 局部,函数内的命名空间就是局部的;
b) 全局,模块内的命名空间就是全局的;

c) 内置,包括异常类型、内建函数和特殊方法,可以代码中任意地方调用;

下面讨论关于名字空间的搜索顺序,先来看张图:

解读Python编程中的命名空间与作用域

命名空间的可见性(作用域)
a) 内置命名空间在代码所有位置都是可见的,所以可以随时被调用;

b) 全局命名空间和局部命名空间中, 如果有同名变量,在全局命名空间处,局部命名空间内的同名变量是不可见的;

c) 在局部命名空间处,全局命名空间的同名变量是不可见的(只有变量不同名的情况下,可使用 global关键字让其可见)。

知道了可见性,下面说变量的查找顺序就要清楚多了。

命名空间的查找顺序
a) 如果在函数内调用一个变量,先在函数内(局部命名空间)查找,如果找到则停止查找。否则在函数外部(全局命名空间)查找,如果还是没找到,则查找内置命名空间。如果以上三个命名都未找到,则抛出NameError 的异常错误。
b) 如果在函数外调用一个变量,则在函数外查找(全局命名空间,局部命名空间此时不可见),如果找到则停止查找,否则到内置命名空间中查找。如果两者都找不到,则抛出异常。只有当局部命名空间内,使用global 关键字声明了一个变量时,查找顺序则是 a) 的查找顺序。

为了帮助理解,来举个例子,我们在全局命名空间里定义一个变量money。我们再在函数内给变量money赋值,然后Python会假定money是一个局部变量。然而,我们并没有在访问前声明一个局部变量money,结果就是会出现一个UnboundLocalError的错误。取消global语句的注释就能解决这个问题。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
Money = 2000
def AddMoney():
  # 想改正代码就取消以下注释:
  # global Money
  Money = Money + 1
 
print Money
AddMoney()
print Money

dir()函数
dir()函数一个排好序的字符串列表,内容是一个模块里定义过的名字。
返回的列表容纳了在一个模块里定义的所有模块,变量和函数。如下一个简单的实例:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
# 导入内置math模块
import math
 
content = dir(math)
 
print content;

以上实例输出结果:

['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 
'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 
'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 
'sqrt', 'tan', 'tanh']

在这里,特殊字符串变量__name__指向模块的名字,__file__指向该模块的导入文件名。

globals()和locals()函数

  • 根据调用地方的不同,globals()和locals()函数可被用来返回全局和局部命名空间里的名字。
  • 如果在函数内部调用locals(),返回的是所有能在该函数里访问的命名。
  • 如果在函数内部调用globals(),返回的是所有在该函数里能访问的全局名字。
  • 两个函数的返回类型都是字典。所以名字们能用keys()函数摘取。

reload()函数
当一个模块被导入到一个脚本,模块顶层部分的代码只会被执行一次。
因此,如果你想重新执行模块里顶层部分的代码,可以用reload()函数。该函数会重新导入之前导入过的模块。语法如下:

reload(module_name)

在这里,module_name要直接放模块的名字,而不是一个字符串形式。比如想重载hello模块,如下:

reload(hello)
Python 相关文章推荐
python通过pil模块将raw图片转换成png图片的方法
Mar 16 Python
浅谈Python生成器generator之next和send的运行流程(详解)
May 08 Python
Python实现抓取网页生成Excel文件的方法示例
Aug 05 Python
CentOS7.3编译安装Python3.6.2的方法
Jan 22 Python
Python中的pack和unpack的使用
Mar 12 Python
Python实现的文本对比报告生成工具示例
May 22 Python
Python全排列操作实例分析
Jul 24 Python
Python3批量生成带logo的二维码方法
Jun 24 Python
twilio python自动拨打电话,播放自定义mp3音频的方法
Aug 08 Python
python保留格式汇总各部门excel内容的实现思路
Jun 01 Python
DataFrame.groupby()所见的各种用法详解
Jun 14 Python
详解用 python-docx 创建浮动图片
Jan 24 Python
Python中的模块导入和读取键盘输入的方法
Oct 16 #Python
Python中基本的日期时间处理的学习教程
Oct 16 #Python
简单介绍使用Python解析并修改XML文档的方法
Oct 15 #Python
Python中将字典转换为XML以及相关的命名空间解析
Oct 15 #Python
详细解读Python中解析XML数据的方法
Oct 15 #Python
深入解析Python编程中JSON模块的使用
Oct 15 #Python
使用Python解析JSON数据的基本方法
Oct 15 #Python
You might like
一个简单的自动发送邮件系统(二)
2006/10/09 PHP
ThinkPHP采用GET方式获取中文参数查询无结果的解决方法
2014/06/26 PHP
php中使用gd库实现远程图片下载实例
2015/05/12 PHP
php版微信公众平台接口开发之智能回复开发教程
2016/09/22 PHP
PHP实现图片的等比缩放和Logo水印功能示例
2017/05/04 PHP
javascript显示隐藏层比较不错的方法分析
2008/09/30 Javascript
原生Js实现元素渐隐/渐现(原理为修改元素的css透明度)
2013/06/24 Javascript
js获取或设置当前窗口url参数的小例子
2013/10/14 Javascript
原生js实现倒计时功能(多种格式调用)
2017/01/12 Javascript
微信小程序 判断手机号的实现代码
2017/04/19 Javascript
JS移动端/H5同时选择多张图片上传并使用canvas压缩图片
2017/06/20 Javascript
在vue中获取dom元素内容的方法
2017/07/10 Javascript
js+html5实现半透明遮罩层弹框效果
2020/08/24 Javascript
Node.js搭建小程序后台服务
2018/01/03 Javascript
vue移动端html5页面根据屏幕适配的四种解决方法
2018/10/19 Javascript
Vue-axios-post数据后端接不到问题解决
2020/01/09 Javascript
js cavans实现静态滚动弹幕
2020/05/21 Javascript
[53:21]2014 DOTA2国际邀请赛中国区预选赛5.21 DT VS LGD-CDEC
2014/05/22 DOTA
[01:32]完美世界DOTA2联赛10月29日精彩集锦
2020/10/30 DOTA
Python检测字符串中是否包含某字符集合中的字符
2015/05/21 Python
简单谈谈python中的语句和语法
2017/08/10 Python
python画一个玫瑰和一个爱心
2020/08/18 Python
python控制nao机器人身体动作实例详解
2019/04/29 Python
python3 深浅copy对比详解
2019/08/12 Python
python 如何在测试中使用 Mock
2021/03/01 Python
美国领先的在线邮轮旅游公司:CruiseDirect
2018/06/07 全球购物
美国庭院家具购物网站:AlphaMarts
2019/04/10 全球购物
班主任寄语大全
2014/04/04 职场文书
小学生个人先进事迹材料
2014/05/08 职场文书
化工工艺设计求职信
2014/06/25 职场文书
最新离婚协议书范本
2014/08/19 职场文书
2014迎国庆演讲稿
2014/09/19 职场文书
2015新年联欢晚会开场白
2014/12/14 职场文书
大学生个人简历自荐信
2015/03/06 职场文书
24句精辟的现实社会语录,句句扎心,道尽人性
2019/08/29 职场文书
剑指Offer之Java算法习题精讲二叉树的构造和遍历
2022/03/21 Java/Android