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实现的简单hangman游戏实例
Jun 28 Python
python连接字符串的方法小结
Jul 13 Python
Python网络编程之TCP套接字简单用法示例
Apr 09 Python
python清除函数占用的内存方法
Jun 25 Python
举例讲解Python常用模块
Mar 08 Python
对python3 sort sorted 函数的应用详解
Jun 27 Python
Python使用type动态创建类操作示例
Feb 29 Python
python读取文件指定行内容实例讲解
Mar 02 Python
如何基于python3和Vue实现AES数据加密
Mar 27 Python
Python grpc超时机制代码示例
Sep 14 Python
基于PyInstaller各参数的含义说明
Mar 04 Python
python 字典和列表嵌套用法详解
Jun 29 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
IIS下PHP连接数据库提示mysql undefined function mysql_connect()
2010/06/04 PHP
PHP原理之异常机制深入分析
2010/08/08 PHP
php 过滤器实现代码
2010/08/09 PHP
web server使用php生成web页面的三种方法总结
2013/10/28 PHP
PHP递归获取目录内所有文件的实现方法
2016/11/01 PHP
基于laravel where的高级使用方法
2019/10/10 PHP
游览器中javascript的执行过程(图文)
2012/05/20 Javascript
jQuery插件FusionCharts绘制的2D双面积图效果示例【附demo源码】
2017/04/11 jQuery
vue2.0的contextmenu右键弹出菜单的实例代码
2017/07/24 Javascript
详解React中的组件通信问题
2017/07/31 Javascript
vue-scroller记录滚动位置的示例代码
2018/01/17 Javascript
AngularJS下$http服务Post方法传递json参数的实例
2018/03/29 Javascript
微信小程序实现语音识别转文字功能及遇到的坑
2019/08/02 Javascript
对vuex中getters计算过滤操作详解
2019/11/06 Javascript
vue前端和Django后端如何查询一定时间段内的数据
2021/02/28 Vue.js
[02:36]DOTA2混沌骑士 英雄基础教程
2013/11/26 DOTA
[46:25]DOTA2上海特级锦标赛主赛事日 - 4 败者组第五轮 MVP.Phx VS EG第二局
2016/03/05 DOTA
[49:59]KG vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python操作SQLite简明教程
2014/07/10 Python
Python标准库urllib2的一些使用细节总结
2015/03/16 Python
Python中exit、return、sys.exit()等使用实例和区别
2015/05/28 Python
详解Django中Request对象的相关用法
2015/07/17 Python
Python读取Json字典写入Excel表格的方法
2018/01/03 Python
kaggle+mnist实现手写字体识别
2018/07/26 Python
Django日志及中间件模块应用案例
2020/09/10 Python
利用简洁的图片预加载组件提升html5移动页面的用户体验
2016/03/11 HTML / CSS
基于Modernizr 让网站进行优雅降级的分析
2013/04/21 HTML / CSS
优衣库台湾官网:UNIQLO台湾
2019/02/01 全球购物
Fanatics法国官网:美国体育电商
2019/08/27 全球购物
新学期开学寄语
2014/01/18 职场文书
餐厅执行经理岗位职责范本
2014/02/26 职场文书
图书馆志愿者活动总结
2014/06/27 职场文书
教学质量月活动总结
2015/05/11 职场文书
实习感想范文
2015/08/10 职场文书
Nginx 匹配方式
2022/05/15 Servers
Nginx 502 bad gateway错误解决的九种方案及原因
2022/08/14 Servers