Python命名空间的本质和加载顺序


Posted in Python onDecember 17, 2018

Python的命名空间是Python程序猿必须了解的内容,对Python命名空间的学习,将使我们在本质上掌握一些Python中的琐碎的规则。

接下来我将分四部分揭示Python命名空间的本质:一、命名空间的定义;二、命名空间的查找顺序;三、命名空间的生命周期;四、通过locals()和globals() BIF访问命名空间

重点是第四部分,我们将在此部分观察命名空间的内容。

一、命名空间

Python使用叫做命名空间的东西来记录变量的轨迹。命名空间是一个 字典(dictionary) ,它的键就是变量名,它的值就是那些变量的值。

A namespace is a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries。

 在一个 Python 程序中的任何一个地方,都存在几个可用的命名空间。

     1、每个函数都有着自已的命名空间,叫做局部命名空间,它记录了函数的变量,包括函数的参数和局部定义的变量。

     2、每个模块拥有它自已的命名空间,叫做全局命名空间,它记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。

     3、还有就是内置命名空间,任何模块均可访问它,它存放着内置的函数和异常。

名称空间的加载顺序

内置命名空间(程序运行前加载)-->全局命名空间(程序运行中:从上到下加载)-->局部命名空间(程序运行中:调用时才加载)

二、名称空间的取值顺序

在局部调用:局部命名空间-->全局命名空间-->内置命名空间

在全局调用:全局命名空间-->内置命名空间

综上所述,在寻找变量时,从小范围,一层一层到大范围去找寻。

三、命名空间查找顺序

当一行代码要使用变量 x 的值时,Python 会到所有可用的名字空间去查找变量,按照如下顺序:

     1、局部命名空间:特指当前函数或类的方法。如果函数定义了一个局部变量 x,或一个参数 x,Python 将使用它,然后停止搜索。

     2、全局命名空间:特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python 将使用它然后停止搜索。

     3、内置命名空间:对每个模块都是全局的。作为最后的尝试,Python 将假设 x 是内置函数或变量。

     4、如果 Python 在这些名字空间找不到 x,它将放弃查找并引发一个 NameError 异常,如,NameError: name 'aa' is not defined。

嵌套函数的情况:

     1、先在当前 (嵌套的或 lambda) 函数的命名空间中搜索

     2、然后是在父函数的命名空间中搜索

     3、接着是模块命名空间中搜索

     4、最后在内置命名空间中搜索

示例:

info = "Adress : "
def func_father(country):
 def func_son(area):
  city= "Shanghai " #此处的city变量,覆盖了父函数的city变量
  print(info + country + city + area)
 city = " Beijing "
 #调用内部函数
 func_son("ChaoYang ");
 
func_father("China ")

输出:Adress : China Shanghai ChaoYang

以上示例中,info在全局命名空间中,country在父函数的命名空间中,city、area在自己函数的命名空间中

四、命名空间的生命周期

不同的命名空间在不同的时刻创建,有不同的生存期。

     1、内置命名空间在 Python 解释器启动时创建,会一直保留,不被删除。

     2、模块的全局命名空间在模块定义被读入时创建,通常模块命名空间也会一直保存到解释器退出。

     3、当函数被调用时创建一个局部命名空间,当函数返回结果 或 抛出异常时,被删除。每一个递归调用的函数都拥有自己的命名空间。

Python 的一个特别之处在于其赋值操作总是在最里层的作用域。赋值不会复制数据——只是将命名绑定到对象。删除也是如此:"del y" 只是从局部作用域的命名空间中删除命名 y 。事实上,所有引入新命名的操作都作用于局部作用域。

示例:

i=1
def func2():
 i=i+1
 
func2();
#错误:UnboundLocalError: local variable 'i' referenced before assignment

由于创建命名空间时,python会检查代码并填充局部命名空间。在python运行那行代码之前,就发现了对i的赋值,并把它添加到局部命名空间中。当函数执行时,python解释器认为i在局部命名空间中但没有值,所以会产生错误。

def func3():
y=123

del y

print(y)

func3()
#错误:UnboundLocalError: local variable 'y' referenced before assignment
#去掉"del y"语句后,运行正常

五、命名空间的访问

1、局部命名空间可以 locals()  BIF来访问。

locals 返回一个名字/值对的 dictionary。这个 dictionary 的键是字符串形式的变量名字,dictionary 的值是变量的实际值。

示例:

def func1(i, str ):
 x = 12345
 print(locals())
 
func1(1 , "first")

输出:{'str': 'first', 'x': 12345, 'i': 1}

2、全局 (模块级别)命名空间可以通过 globals() BIF来访问。

示例:

import copy
from copy import deepcopy
 
gstr = "global string"
 
def func1(i, info):
 x = 12345
 print(locals())
 
func1(1 , "first")
 
if __name__ == "__main__":
 print("the current scope's global variables:")
 dictionary=globals()
 print(dictionary)

输出:(我自己给人为的换行、更换了顺序,加颜色的语句下面重点说明)

{

'__name__': '__main__',

'__doc__': 'Created on 2013-5-26', 

'__package__': None,

'__cached__': None,

'__file__': 'E:\\WorkspaceP\\Test1\\src\\base\\test1.py',

'__loader__': <_frozen_importlib.SourceFileLoader object at 0x01C702D0>,

'copy': <module 'copy' from 'D:\\Python33\\lib\\copy.py'>,

'__builtins__': <module 'builtins' (built-in)>,

'gstr': 'global string',

'dictionary': {...},

'func1': <function func1 at 0x01C6C540>,

'deepcopy': <function deepcopy at 0x01DB28A0>

}

总结

1、模块的名字空间不仅仅包含模块级的变量和常量,还包括所有在模块中定义的函数和类。除此以外,它还包括了任何被导入到模块中的东西。

2、我们看到,内置命名也同样被包含在一个模块中,它被称作 __builtin__。

3、回想一下 from module import 和 import module 之间的不同。

使用 import module,模块自身被导入,但是它保持着自已的名字空间,这就是为什么您需要使用模块名来访问它的函数或属性:module.function 的原因。

但是使用 from module import function,实际上是从另一个模块中将指定的函数和属性导入到您自己的名字空间,这就是为什么您可以直接访问它们却不需要引用它们所来源的模块。使用 globals 函数,您会真切地看到这一切的发生,见上面的红色输出语句。

3、 locals 与 globals 之间的一个重要的区别

locals 是只读的,globals 不是

示例:

def func1(i, info):
 x = 12345
 print(locals())
 locals()["x"]= 6789
 print("x=",x)
 
y=54321
func1(1 , "first")
globals()["y"]= 9876
print( "y=",y)

输出:

{'i': 1, 'x': 12345, 'info': 'first'}

x= 12345

y= 9876

解释:

locals 实际上没有返回局部名字空间,它返回的是一个拷贝。所以对它进行改变对局部名字空间中的变量值并无影响。

globals 返回实际的全局名字空间,而不是一个拷贝。所以对 globals 所返回的 dictionary 的任何的改动都会直接影响到全局变量。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现二维码扫码自动登录淘宝
Dec 27 Python
python ddt实现数据驱动
Mar 14 Python
Python连接Redis的基本配置方法
Sep 13 Python
Python 监测文件是否更新的方法
Jun 10 Python
在django中图片上传的格式校验及大小方法
Jul 28 Python
python中调试或排错的五种方法示例
Sep 12 Python
TensorFlow梯度求解tf.gradients实例
Feb 04 Python
python 日志 logging模块详细解析
Mar 31 Python
python全栈开发语法总结
Nov 22 Python
Python hashlib和hmac模块使用方法解析
Dec 08 Python
python的dict判断key是否存在的方法
Dec 09 Python
实战Python爬虫爬取酷我音乐
Apr 11 Python
对python的unittest架构公共参数token提取方法详解
Dec 17 #Python
Python单元测试unittest的具体使用示例
Dec 17 #Python
Python使用Selenium爬取淘宝异步加载的数据方法
Dec 17 #Python
在scrapy中使用phantomJS实现异步爬取的方法
Dec 17 #Python
Python 通过调用接口获取公交信息的实例
Dec 17 #Python
python用插值法绘制平滑曲线
Feb 19 #Python
selenium在执行phantomjs的API并获取执行结果的方法
Dec 17 #Python
You might like
解析posix与perl标准的正则表达式区别
2013/06/17 PHP
thinkphp3.x中session方法的用法分析
2016/05/20 PHP
PHP读取文本文件并逐行输出该行使用最多的字符与对应次数的方法
2016/11/25 PHP
fancybox modal的完美解决(右上的X)
2012/10/30 Javascript
jquery Mobile入门—外部链接切换示例代码
2013/01/08 Javascript
JavaScript判断DIV内容是否为空的方法
2016/01/29 Javascript
javascript 数据存储的常用函数总结
2017/06/01 Javascript
layui.js实现的表单验证功能示例
2017/11/15 Javascript
浅谈发布订阅模式与观察者模式
2019/04/09 Javascript
react高阶组件添加和删除props
2019/04/26 Javascript
js判断非127开头的IP地址的实例代码
2020/01/05 Javascript
使用Typescript开发微信小程序的步骤详解
2021/01/12 Javascript
解决python文件字符串转列表时遇到空行的问题
2017/07/09 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
2017/08/24 Python
对python中的logger模块全面讲解
2018/04/28 Python
Python做智能家居温湿度报警系统
2018/09/25 Python
python实现文本进度条 程序进度条 加载进度条 单行刷新功能
2019/07/03 Python
django框架中ajax的使用及避开CSRF 验证的方式详解
2019/12/11 Python
NumPy排序的实现
2020/01/21 Python
TensorFlow2.X使用图片制作简单的数据集训练模型
2020/04/08 Python
使用python tkinter开发一个爬取B站直播弹幕工具的实现代码
2021/02/07 Python
纯CSS3实现地球自转实现代码(图文教程附送源码)
2012/12/26 HTML / CSS
Html5之title吸顶功能
2018/06/04 HTML / CSS
Get The Label中文官网:英国运动时尚购物平台
2017/04/19 全球购物
亚马逊印度站:Amazon.in
2017/10/15 全球购物
数据库的约束含义
2012/09/09 面试题
医学院学生求职简历的自我评价
2013/10/24 职场文书
工程造价与管理专业应届生求职信
2013/11/23 职场文书
检查接待方案
2014/02/27 职场文书
诉讼代理人授权委托书
2014/04/08 职场文书
毕业生面试求职信
2014/06/23 职场文书
民主评议党员工作总结
2014/10/20 职场文书
2015年惩防体系建设工作总结
2015/05/22 职场文书
红色经典电影观后感
2015/06/18 职场文书
2015年中学图书馆工作总结
2015/07/22 职场文书
python实现自动化群控的步骤
2021/04/11 Python