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实现从web抓取文档的方法
Sep 26 Python
浅谈对yield的初步理解
May 29 Python
python对配置文件.ini进行增删改查操作的方法示例
Jul 28 Python
python3+PyQt5实现文档打印功能
Apr 24 Python
python 3.6.4 安装配置方法图文教程
Sep 18 Python
在python环境下运用kafka对数据进行实时传输的方法
Dec 27 Python
Python实现读取txt文件中的数据并绘制出图形操作示例
Feb 26 Python
python判断变量是否为int、字符串、列表、元组、字典的方法详解
Feb 13 Python
关于Python字符编码与二进制不得不说的一些事
Oct 04 Python
Python实现哲学家就餐问题实例代码
Nov 09 Python
python小技巧——将变量保存在本地及读取
Nov 13 Python
Python urllib request模块发送请求实现过程解析
Dec 10 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
PHP 删除文件与文件夹操作 unlink()与rmdir()这两个函数的使用
2011/07/17 PHP
php环境下利用session防止页面重复刷新的具体实现
2014/01/09 PHP
defer属性导致引用JQuery的页面报“浏览器无法打开网站xxx,操作被中止”错误的解决方法
2010/04/27 Javascript
jQuery1.3.2 升级到jQuery1.4.4需要修改的地方
2011/01/06 Javascript
javascript学习(一)构建自己的JS库
2013/01/02 Javascript
JavaScript常用的返回,自动跳转,刷新,关闭语句汇总
2015/01/13 Javascript
vue.js 表格分页ajax 异步加载数据
2016/10/18 Javascript
微信小程序 swiper组件详解及实例代码
2016/10/25 Javascript
JS简单实现数组去重的方法示例
2017/03/27 Javascript
nodejs入门教程二:创建一个简单应用示例
2017/04/24 NodeJs
JS实现简单抖动效果
2017/06/01 Javascript
微信小程序搜索组件wxSearch实例详解
2017/06/08 Javascript
让nodeJS支持ES6的词法----babel的安装和使用方法
2017/07/31 NodeJs
vue 2.0项目中如何引入element-ui详解
2017/09/06 Javascript
微信小程序报错:this.setData is not a function的解决办法
2017/09/27 Javascript
Vue 父子组件数据传递的四种方式( inheritAttrs + $attrs + $listeners)
2018/05/04 Javascript
JS实现的杨辉三角【帕斯卡三角形】算法示例
2019/02/26 Javascript
Angular利用HTTP POST下载流文件的步骤记录
2020/07/26 Javascript
vant 中van-list的用法说明
2020/11/11 Javascript
Python中itertools模块用法详解
2014/09/25 Python
Python中使用Flask、MongoDB搭建简易图片服务器
2015/02/04 Python
Python代码解决RenderView窗口not found问题
2016/08/28 Python
ansible作为python模块库使用的方法实例
2017/01/17 Python
python解释器pycharm安装及环境变量配置教程图文详解
2020/02/26 Python
django模板获取list中指定索引的值方式
2020/05/14 Python
Pycharm插件(Grep Console)自定义规则输出颜色日志的方法
2020/05/27 Python
CSS实现fullpage.js全屏滚动效果的示例代码
2021/03/24 HTML / CSS
祖国在我心中演讲稿500字
2014/05/04 职场文书
加薪申请报告范本
2015/05/15 职场文书
2015年学校政教工作总结
2015/07/20 职场文书
《静夜思》教学反思
2016/02/17 职场文书
详解MySQL事务的隔离级别与MVCC
2021/04/22 MySQL
python爬取豆瓣电影TOP250数据
2021/05/23 Python
MySQL学习之基础操作总结
2022/03/19 MySQL
进行数据处理的6个 Python 代码块分享
2022/04/06 Python
一行Python命令实现批量加水印
2022/04/07 Python