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网络编程学习笔记(九):数据库客户端 DB-API
Jun 09 Python
python求pi的方法
Oct 08 Python
Python实现测试磁盘性能的方法
Mar 12 Python
python使用PIL模块实现给图片打水印的方法
May 22 Python
Python计算已经过去多少个周末的方法
Jul 25 Python
python中range()与xrange()用法分析
Sep 21 Python
windows下ipython的安装与使用详解
Oct 20 Python
python pygame实现挡板弹球游戏
Nov 25 Python
Python面向对象程序设计之类和对象、实例变量、类变量用法分析
Mar 23 Python
pytorch下的unsqueeze和squeeze的用法说明
Feb 06 Python
pandas数值排序的实现实例
Jul 25 Python
Python编程中内置的NotImplemented类型的用法
Mar 23 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开发GUI
2006/10/09 PHP
基于session_unset与session_destroy的区别详解
2013/06/03 PHP
php微信公众平台配置接口开发程序
2016/09/22 PHP
jQuery链使用指南
2015/01/20 Javascript
详解javascript的变量与标识符
2016/01/04 Javascript
mvvm双向绑定机制的原理和实现代码(推荐)
2016/06/07 Javascript
解析js如何获取css样式
2016/12/11 Javascript
JavaScript取得gridview中获取checkbox选中的值
2017/07/24 Javascript
vue input输入框模糊查询的示例代码
2018/05/22 Javascript
vue中vee validate表单校验的几种基本使用
2018/06/25 Javascript
Vuex的初探与实战小结
2018/11/26 Javascript
JavaScript函数式编程(Functional Programming)纯函数用法分析
2019/05/22 Javascript
ES6 Promise对象概念及用法实例详解
2019/10/15 Javascript
详解JavaScript之Array.reduce源码解读
2020/11/01 Javascript
[01:15]《辉夜杯》北京网鱼队巡礼
2015/10/26 DOTA
python进阶教程之函数对象(函数也是对象)
2014/08/30 Python
在Python程序中进行文件读取和写入操作的教程
2015/04/28 Python
介绍Python中内置的itertools模块
2015/04/29 Python
通过Python来使用七牛云存储的方法详解
2015/08/07 Python
python tensorflow基于cnn实现手写数字识别
2018/01/01 Python
深入浅析python 中的匿名函数
2018/05/21 Python
python之cv2与图像的载入、显示和保存实例
2018/12/05 Python
Python 多维List创建的问题小结
2019/01/18 Python
python常用库之NumPy和sklearn入门
2019/07/11 Python
递归实现回文判断(如:abcdedbca就是回文,判断一个面试者对递归理解的简单程序)
2013/04/28 面试题
师范毕业生求职自荐信
2013/09/25 职场文书
注塑工厂厂长岗位职责
2013/12/02 职场文书
《陈涉世家》教学反思
2014/04/12 职场文书
人力资源求职信
2014/05/25 职场文书
生物科学专业毕业生求职信
2014/06/02 职场文书
奉献家乡演讲稿
2014/09/16 职场文书
2014年财务科工作总结
2014/11/11 职场文书
2014年酒店前台工作总结
2014/11/14 职场文书
2015年清明节演讲稿范文
2015/03/17 职场文书
怒海潜将观后感
2015/06/11 职场文书
2015暑期社会实践个人总结
2015/07/13 职场文书