Python命名空间的本质和加载顺序

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 的任何的改动都会直接影响到全局变量。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Python命名空间详解

    通俗的来说,Python中所谓的命名空间可以理解为一个容器.在这个容器中可以装许多标识符.不同容器中的同名的标识符是不会相互冲突的.理解python的命名空间需要掌握三条规则: 第一,赋值(包括显式赋值和隐式赋值)产生标识符,赋值的地点决定标识符所处的命名空间. 第二,函数定义(包括def和lambda)产生新的命名空间. 第三,python搜索一个标识符的顺序是"LEGB". 所谓的"LEGB"是python中四层命名空间的英文名字首字母的缩写. 最里面的一层是L

  • python命名空间(namespace)简单介绍

    命名空间: 每一个作用域变量存储的位置,或者解释为 存储作用域中变量的字典. 作用: 获取想查看某个作用域中的变量名.变量值. 使用方法: locals() #当前命名空间 1. 效果图: 2. 代码 a=10 b=20 # 定义一个变量接收全局命名空间里的变量名.变量值 global_namespace=locals() print(global_namespace) print('\n\n\n') def one(): c=30 d=40 # 定义一个变量接收局部命名空间里的变量名.变量值

  • 解读Python编程中的命名空间与作用域

    变量是拥有匹配对象的名字(标识符).命名空间是一个包含了变量名称们(键)和它们各自相应的对象们(值)的字典. 一个Python表达式可以访问局部命名空间和全局命名空间里的变量.如果一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量. 每个函数都有自己的命名空间.类的方法的作用域规则和通常函数的一样. Python会智能地猜测一个变量是局部的还是全局的,它假设任何在函数内赋值的变量都是局部的. 因此,如果要给全局变量在一个函数里赋值,必须使用global语句. global VarName的

  • Python动态参数/命名空间/函数嵌套/global和nonlocal

    1. 函数的动态参数 1.1 *args 位置参数动态传参 def chi(*food): print("我要吃", food) chi("大米饭", "小米饭") 结果:我要吃 ('大米饭', '小米饭') # 多个参数传递进去. 收到的内容是元组tuple 1.2 **kwargs 关键字参数动态传参 def func(**kwargs): print(kwargs) func(a=1, b=2, c=3) func(a=1, b=2) 结果

  • Python进阶_关于命名空间与作用域(详解)

    写在前面 如非特别说明,下文均基于Python3 命名空间与作用于跟名字的绑定相关性很大,可以结合另一篇介绍Python名字.对象及其绑定的文章. 1. 命名空间 1.1 什么是命名空间 Namespace命名空间,也称名字空间,是从名字到对象的映射.Python中,大部分的命名空间都是由字典来实现的,但是本文的不会涉及命名空间的实现.命名空间的一大作用是避免名字冲突: def fun1(): i = 1 def fun2(): i = 2 同一个模块中的两个函数中,两个同名名字i之间绝没有任何

  • Python函数基础实例详解【函数嵌套,命名空间,函数对象,闭包函数等】

    本文实例讲述了Python函数基础用法.分享给大家供大家参考,具体如下: 一.什么是命名关键字参数? 格式: 在*后面参数都是命名关键字参数. 特点: 1.约束函数的调用者必须按照Kye=value的形式传值. 2.约束函数的调用者必须用我们指定的Key名. def auth(*args,name,pwd): print(name,pwd) auth(pwd='213',name='egon') def register(name,age): print(type(name),type(age)

  • Python中将字典转换为XML以及相关的命名空间解析

    尽管 xml.etree.ElementTree 库通常用来做解析工作,其实它也可以创建XML文档. 例如,考虑如下这个函数: from xml.etree.ElementTree import Element def dict_to_xml(tag, d): ''' Turn a simple dict of key/value pairs into XML ''' elem = Element(tag) for key, val in d.items(): child = Element(k

  • Python命名空间的本质和加载顺序

    Python的命名空间是Python程序猿必须了解的内容,对Python命名空间的学习,将使我们在本质上掌握一些Python中的琐碎的规则. 接下来我将分四部分揭示Python命名空间的本质:一.命名空间的定义:二.命名空间的查找顺序:三.命名空间的生命周期:四.通过locals()和globals() BIF访问命名空间 重点是第四部分,我们将在此部分观察命名空间的内容. 一.命名空间 Python使用叫做命名空间的东西来记录变量的轨迹.命名空间是一个 字典(dictionary) ,它的键就

  • Python 关于模块和加载模块的实现

    一.导入模块 模块(Modules) 模块就是Python程序,任何Python程序都可以作为模块 代码的可重用性,只要编程过程中需要用到该模块中的某个功能(由变量.函数.类实现),直接在程序中导入该模块即可使用该功能 封装特性的结构: 诸多容器,列表.元组.字符串.字典等都是对数据的封装 函数是对 Python 代码的封装 类是对方法和属性的封装,是对函数和数据的封装 模块,可以理解是对代码更高级的封装,把能够实现某一特定功能的代码编写在同一个.py 文件中,并将其作为一个独立的模块,还能有效

  • PHP命名空间和自动加载类

    PHP的命名空间(namespace)是php5.3之后才有的.这个概念在C#中已经很早就有了,php中的namespace其实和c#的概念是一样的. 为什么php中要使用namespace? 假设如果不使用namespace,那么每个类在一个项目中的名字就必须是固定的.因为php在new的时候不管是调用autoload还是调用已加载过的类,都存在一个类名对应的文件.所以在没有namespace的时候,我们会想各种命名规则来区分不同的类,比如project1_school1_class1_Stu

  • PyTorch深度学习模型的保存和加载流程详解

    一.模型参数的保存和加载 torch.save(module.state_dict(), path):使用module.state_dict()函数获取各层已经训练好的参数和缓冲区,然后将参数和缓冲区保存到path所指定的文件存放路径(常用文件格式为.pt..pth或.pkl). torch.nn.Module.load_state_dict(state_dict):从state_dict中加载参数和缓冲区到Module及其子类中 . torch.nn.Module.state_dict()函数

  • PHP命名空间与自动加载类详解

    本文实例讲述了PHP命名空间与自动加载类.分享给大家供大家参考,具体如下: 今天我要给大家介绍的是PHP的命名空间 和 自动加载类 我先简单的分开演示 在放在一起 大家请看: 什么是自动加载类? 想必大家都应该知道__autoload 这个魔术方法 $db = new DB(); function __autoload($className) { echo $className; exit(); //在这个里面引用类 } 在运用这个类只能加载一次 ,在很多时候我们要引入的不止一个类这个时候怎么办

  • Django框架模板文件使用及模板文件加载顺序分析

    本文实例讲述了Django框架模板文件使用及模板文件加载顺序.分享给大家供大家参考,具体如下: 模板功能 产生html,控制页面上产生的内容.模板文件不仅仅是一个html文件. 模板文件包含两部分内容: 1.静态文件:css,js,html 2.动态内容:用于动态的去产生一些网页内容,通过模板语言产生 模板文件的使用 通常是在视图函数中使用模板产生html内容返回给客户端 a,加载模板文件 loader.get_template 获取模板文件的内容,产生一个模板对象 b,定义模板上下文 Requ

  • python用pandas数据加载、存储与文件格式的实例

    数据加载.存储与文件格式 pandas提供了一些用于将表格型数据读取为DataFrame对象的函数.其中read_csv和read_talbe用得最多 pandas中的解析函数: 函数 说明 read_csv 从文件.URL.文件型对象中加载带分隔符的数据,默认分隔符为逗号 read_table 从文件.URL.文件型对象中加载带分隔符的数据.默认分隔符为制表符("\t") read_fwf 读取定宽列格式数据(也就是说,没有分隔符) read_clipboard 读取剪贴板中的数据,

  • 解决tensorflow模型参数保存和加载的问题

    终于找到bug原因!记一下:还是不熟悉平台的原因造成的! Q:为什么会出现两个模型对象在同一个文件中一起运行,当直接读取他们分开运行时训练出来的模型会出错,而且总是有一个正确,一个读取错误? 而 直接在同一个文件又训练又重新加载模型预测不出错,而且更诡异的是此时用分文件里的对象加载模型不会出错? model.py,里面含有 ModelV 和 ModelP,另外还有 modelP.py 和 modelV.py 分别只含有 ModelP 和 ModeV 这两个对象,先使用 modelP.py 和 m

  • PHP 命名空间和自动加载原理与用法实例分析

    本文实例讲述了PHP 命名空间和自动加载原理与用法.分享给大家供大家参考,具体如下: PHP 命名空间 php5.3 之后引入了命名空间的特性,从本质上讲,命名空间就是一个容器,你可以将类.函数和变量放在其中,在命名空间中,你可以无条件地访问这些项,在命名空间之外,必须导入或引用命名空间,才能访问它所包含的项. 声明命名空间 namespace my; require_one 'outputter3.php'; class outputter { // 输出数据 public function

  • windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码

    最近在上<自然语言处理>这门选修课,为了完成上机作业也是很认真了,这次是为了实现语角色标注任务,于是就入了这个坑,让我们来(快乐地 )解决出现的问题. 问题一:下载安装pyltp实现语义角色标注是在python3.6环境下实现的,(别问我怎么知道的,自己安装失败n次,问了室友才知道的 ),如果你的pycharm解释器安装的是3.7的该咋办呢? 答:再下载一个Python3.6在电脑的环境变量里把3.6的放到3.7的前面,这样就可以了,具体实施如下: 1.去Python官网下一个3.6版本的应用

随机推荐