命名空间(代码片段)

Yellow_huang Yellow_huang     2022-11-18     561

关键词:

 

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

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

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

一、命名空间

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、最后在内置命名空间中搜索
 
示例:
技术分享图片
 1 info = "Adress : "
 2 def func_father(country):
 3     def func_son(area):
 4         city= "Shanghai " #此处的city变量,覆盖了父函数的city变量
 5         print(info + country + city + area)
 6     city = " Beijing "
 7     #调用内部函数
 8     func_son("ChaoYang ");
 9  
10 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来访问。
示例:
技术分享图片
‘‘‘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 的任何的改动都会直接影响到全局变量。

 

phpphp命名空间(代码片段)

查看详情

javascriptjavascript命名空间(代码片段)

查看详情

javascriptjavascript命名空间(代码片段)

查看详情

htmlviewhelper命名空间(代码片段)

查看详情

作用域与命名空间(代码片段)

python命名空间的本质一、命名空间Python使用叫做命名空间的东西来记录变量的轨迹。命名空间是一个字典(dictionary),它的键就是变量名,它的值就是那些变量的值。Anamespaceisamappingfromnamestoobjects.MostnamespacesarecurrentlyimplementedasPy... 查看详情

phpphalcon注册命名空间(代码片段)

查看详情

sh杀死命名空间(代码片段)

查看详情

javascript命名空间功能(代码片段)

查看详情

django(命名空间)(代码片段)

 命名空间命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识... 查看详情

第七天(代码片段)

第一部分命名空间 命名空间:保存名字的容器名字:定义函数名字、变量名字、类名字、模块、包...容器:list,tuple,set形式:键(名字)值(内存对象)对每个函数、变量都有自己的命名空间在哪定义?什么时候定义?函数... 查看详情

9.类名与命名空间(代码片段)

1#include<iostream>2usingnamespacestd;34//扩展标准命名空间5//数据类型可以放在命名空间,避免冲突6namespacestd78//拥有class所有功能9structdata1011inta;12intb;13//声明14intgetadd();15;161718//实现19intstd::data::getadd()//命名空间:: 查看详情

xml名命空间(代码片段)

XML的名命空间就类似于java的包,命名空间定义:xmlns:***="URL",默认命名空间定义:xmlns="URL"引号中的URL内容用来唯一标识命名空间,不能重复。上面定义的***可用于元素或属性,使用格式:***:元素名/属性名,后面部分不变。在... 查看详情

texttinyrefl解析器错误,找不到全局命名空间中的命名空间(代码片段)

查看详情

c++命名空间与缺省参数(代码片段)

目录命名空间为什么引入命名空间命名空间定义使用命名空间标准命名空间缺省参数缺省参数概念缺省参数分类全缺省参数半缺省参数命名空间为什么引入命名空间在C++中,变量、函数和类都是大量存在的,这些变... 查看详情

javascriptgraphql命名空间架构示例(代码片段)

查看详情

csharp9.命名空间(代码片段)

查看详情

javascript命名空间hoc(代码片段)

查看详情

phpcomposer命名空间autoload(代码片段)

查看详情