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

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

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

一、命名空间

Python使用叫做命名空间的东西来记录变量的轨迹命名空间是一个 字典(dictionary) ,它的键就是变量名,它的值就是那些变量的值
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() 来访问。
locals 返回一个名字/值对的 dictionary。这个 dictionary 的键是字符串形式的变量名字,dictionary 的值是变量的实际值。
示例:

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

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

 
2、全局 (模块级别)命名空间可以通过 globals()来访问。
示例:
 '''Created on 2013-5-26'''

 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命名空间的本质的更多相关文章

  1. python命名空间与作用域

    python命名空间与作用域   命名空间是名称与对象之间的关系,可以将命名空间看做是字典,其中的键是名称,值是对象. 命名空间不共享名称. 在命名空间中的名称能将任何python对象作为值,在不同的 ...

  2. [Python] 命名空间&作用域

    Python的类语句不会创建实例 类会创建命名空间,通过对象访问类的属性和方法 类不会创建作用域,对方法和属性的引用必须加以限定(如在方法中必须通过self引用实例的属性) class My1(): ...

  3. python命名空间、作用域、闭包与传值传引用

    (以下内容,均基于python3) 最近在看python函数部分,讲到了python的作用域问题,然后又讲了Python的闭包问题. 在做作业的时候,我遇到了几个问题,下面先来看作业. 一. 作业1: ...

  4. python命名空间

    在"python之禅"那几句话中有一句:namespace is a good thing. python对于命名空间的处理非常简单,下面的内容不一定真实,完全是我根据现象推测出来 ...

  5. Python 命名空间

    通俗的来说,Python中所谓的命名空间可以理解为一个容器.在这个容器中可以装许多标识符.不同容器中的同名的标识符是不会相互冲突的.理解python的命名空间需要掌握三条规则: 第一,赋值(包括显式赋 ...

  6. 详解python命名空间和作用域

    1.典型案例 先从几个典型的案例来看下名称空间及作用域对python代码运行的影响,请看下面几个代码实例及其执行结果,是否符合你的预期. 代码1:块作用域 if True: i = 1 print i ...

  7. python类和模块区别,python命名空间

    在python中,类可以提供模块级别之下的命名空间. 如果一个模块写很多函数,某些函数之间共同完成一组功能,用类会看起来更清晰,在调用时候也会更好,对于ide补全有更小范围的限定提示. 类提供 继承 ...

  8. python—命名空间、作用域查找顺序、闭包

    名称空间 name space,如下图: x = 1, 1存放在内存中,1 会有一个内存地址,x 则 存放在 name space 里,并同时记录了 1的内存地址, 即 名称空间是存放了变量x与1绑定 ...

  9. Python命名空间和作用域

    准备知识: 1.在Python解释器开始执行之后,机会在内存中开辟一个空间,每当遇到 一个变量的时候,就把变量和值之间的关系记录下来,但是当遇到函数定义 的时候,解释器只是把函数名读入内存,表示这个函 ...

随机推荐

  1. linux搭建svn服务并手动同步代码到web目录和自动更新

    1.安装svn服务端 yum -y install subversion 2.查看安装路径等信息 rpm -ql subversion 3.查看svn帮助信息 svn help 4.创建svn版本库目 ...

  2. 两种ajax的方法

    两种Ajax方法 Ajax是一种用于快速创建动态网页的技术,他通过在后台与服务器进行少量的数据交换,可以实现网页的异步更新,不需要像传统网页那样重新加载页面也可以做到对网页的某部分作出更新,现在这项技 ...

  3. RabbitMQ学习之(一)_初步了解RabbitMQ、RabbitMQ的使用流程、为什么要使用RabbitMQ、RabbitMQ的应用场景

    初识RabbitMQ RabbitMQ是一个在AMQP协议基础上实现的消息队列系统, 是一个消息代理.它的核心原理非常简单:接收和发送消息.你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件 ...

  4. 20145312 实验二《 Java面向对象程序设计》

    20145312 实验二< Java面向对象程序设计> 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解 ...

  5. 20144303 《Java程序设计》第三周学习总结

    20144303 <Java程序设计>第三周学习总结 教材学习内容总结 •对象是存在的具体实体,具有明确的状态和行为,类是具有相同属性和行为的一组对象的集合,用于组合各个对象所共有操作和属 ...

  6. JavaScript 数据类型小结

    数据类型对于机器而言,其意义在于更加合理的分配内存空间,而对于编程者而言,数据类型提供了我们相对应的一系列方法,对数据进行分析与处理. 在本文中,将对JavaScript数据类型的基础知识进行总结,全 ...

  7. ThinkPHP将上传问件添加到数据库

    <?php namespace Home\Controller; /***************** use Think\Controller; ****命名空间****/ class Mes ...

  8. creator cocos2d-js-min.js 文件廋身 变小 太大解决方法

    使用的 cocos creator 1.2 版本, 菜单栏 项目 -- 项目设置 -- 模块设置 里面 把不要的模块去掉

  9. Vue中使用百度地图——根据输入框输入的内容,获取详细地址

    知识点:在Vue.js项目中调用百度地图API,实现input框,输入地址,在百度地图上定位到准确地址,获得到经纬度 参考博客:  百度地图的引用,初步了解参考博客:http://blog.csdn. ...

  10. 【Network Architecture】SegNet论文解析(转)

    文章来源: https://blog.csdn.net/fate_fjh/article/details/53467948 Introduction 自己制作国内高速公路label,使用SegNet训 ...