命名空间和作用域的概念我们之前也提到过,比如内置函数globals(),函数中变量的作用域,模块使用的import等等。这些可能让我们对这两个概念有了大致的理解。本节再详细探讨一下。

Python命名空间

命名空间,就是一个从名称到对象的映射关系。

对于这个概念的理解,我们打个比方:河西村有个人(对象)叫张三(名称),河东村有个人(对象)也叫张三(名称),俩人虽然都叫张三(名称),但是他们俩不是同一个人(对象),因为他们属于不同的村(命名空间)。有一天,河西村的张三名声大了,传播到镇上了(名称被import到“镇”这个空间),镇上的人讲起“张三”时,就是说的河西村的,要是说河东村的张三,就要特别说“河东村的张三”(河东村.张三)。这就是命名空间的意思——映射了名称到对象的名称范围。

目前,大部分的命名空间都是由Python的字典实现的,通常我们不会去关注它们,处理要面对性能问题时,并且这种实现可能在将来改变。所以说,我们不需要深究命名空间的内部实现,但要搞明白它的使用。

下面是几个命名空间的例子:

内置函数的集合(包含print()等内置函数和内置异常等);

模块中的全局名称;

函数调用中的本地名称。

另外,从某种含义上说,对象的属性集合也是一种命名空间的形式。正如我们前面举的张三的例子那样,不同命名空间中的名称之间没有任何关系。比如,两个不同模块都可以定义函数max()而不会产生混淆,模块的用户要调用某个max()函数就要在其前面加上模块名称。(详见import的使用)

Python属性

我们把任何跟在一个点号之后的名称都称为属性。例如,在表达式a.name中,real是对象a的一个属性。同样对模块中函数的引用也是属性引用,在表达式modname.funcname中,modname是一个模块对象,而funcname是它的一个属性。

属性可以是只读的也可以是可写的。如果是可写的,那么我们就可以对属性进行赋值,比如,modname.name = '猿人学Python'。可写的属性同样可以用del语句删除,比如del modname.name将把modname对象的name属性移除。

不同时刻创建的命名空间有不同的生存期:

包含内置名称的命名空间是在Python解释器启动时创建的,永远不会被删除(除非退出解释器);

模块的全局命名空间在模块定义被读入(import)时创建,通常,模块命名空间也会持续到解释器退出;

从脚本文件(.py或.pyc)读取或交互式(解释器shell)读取而被解释器的顶层调用执行的语句,被认为是__main__模块调用的一部分,它们有自己的全局命名空间;

函数的本地命名空间创建于该函数被调用的时刻,并且在函数返回或抛出一个不在函数内部处理的异常时被删除。递归函数的每次递归调用都会创建它自己的本地命名空间;

内置名称实际上也存在于一个模块中,它叫做builtins。

Python作用域

作用域,是一个命名空间可直接发放完的Python代码的文本区域。这里的“可直接访问”的意思是,对名称的不加点号(非限定性)引用会尝试在命名空间中查找该名称。

尽管作用域是静态确定的,但它们是动态使用的。在执行期间的任何时刻,至少有三个嵌套的作用域,它们的命名空间可以直接访问:

最内部作用域:最先搜索该作用域,包含局部名称

封闭函数作用域:从最近的封闭作用域开始搜索,包含非局部名称,也包括非全局名称

倒数第二个作用域:包含当前模块的全局名称

最外面的作用域:最后搜索,是包含内置名称的命名空间

如果一个名称被声明为全局变量,则所有引用和赋值将直接指向包含该模块的全局名称的中间作用域。 要重新绑定在最内层作用域以外找到的变量,可以使用nonlocal语句声明为非本地变量。 如果没有被声明为非本地变量,这些变量将是只读的(尝试写入这样的变量只会在最内层作用域中创建一个新的局部变量,而同名的外部变量保持不变)。

很重要的一点:作用域是按文本方式确定的,模块内定义的函数的全局作用域就是该模块的命名空间,无论该函数从什么地方或以什么别名被调用。另一方面,实际的名称搜索是在运行时动态完成的。

Python 的一个特殊之处在于: 如果不存在生效的global语句,对名称的赋值总是进入最内层作用域。 赋值不会复制数据,它们只是将名称绑定到对象。删除也是如此,语句del x会从局部命名空间的引用中移除对x的绑定。事实上,所有引入新名称的操作都使用局部作用域,特别是import语句和函数定义会在局部作用域中绑定模块或函数名称。

global语句可被用来表明特定变量生存于全局作用域并且应当在其中被重新绑定;nonlocal语句表明特定变量生存于外层作用域中并且应当在其中被重新绑定。

下面我们来看一个作用域和命名空间的例子,它演示流量如何引用不同作用域和命名空间以及global和nonlocal如何影响变量绑定:

def scope_demo():

def do_local():

name = 'local name'

def do_nonlocal():

nonlocal name

name = 'nonlocal name'

def do_global():

global name

name = 'global name'

name = 'demo name'

do_local()

print('After local assignment:', name)

do_nonlocal()

print('After nonlocal assignment:', name)

do_global()

print('After global assignment:', name)

scope_demo()

print('In global scope:', name)

思考一下,上面的代码会输出怎样的结果?如果你对上面的讲解理解透了,你的思考结果应该是这样的:

After local assignment: demo name

After nonlocal assignment: nonlocal name

After global assignment: nonlocal name

In global scope: global name

这里要说明的是,do_global()函数修改了全局变量name,并没有对scope_demo()函数的局部变量name做修改,所以打印了After global assignment: nonlocal name。

局部赋值(默认情况)不会改变scope_demo对name的绑定;nonlocal赋值会改变函数scope_demo对name的绑定,而global赋值会改变模块层级的绑定(不是scope_demo内部的name,而是其之外的全局作用域下的name)。

命令空间和作用域总结:

命名空间定义了一个名称的范围,作用域指定了能看到命名空间的文本区域(代码)。代码执行时,名称搜索的顺序和范围如下:

最内部作用域:最先搜索该作用域,包含局部名称

封闭函数作用域:从最近的封闭作用域开始搜索,包含非局部名称,也包括非全局名称

倒数第二个作用域:包含当前模块的全局名称

最外面的作用域:最后搜索,是包含内置名称的命名空间

相关练习题

参照scope_demo(),练习局部赋值、nonlocal赋值、global赋值。

我的公众号:猿人学 Python 上会分享更多心得体会,敬请关注。

***版权申明:若没有特殊说明,文章皆是猿人学 yuanrenxue.com 原创,没有猿人学授权,请勿以任何形式转载。***

python的作用域分别有几种_Python作用域和命名空间相关推荐

  1. python的作用域分别有几种_python 作用域知识点整理

    1.块级作用域 想想此时运行下面的程序会有输出吗?执行会成功吗? 1 2 3 4 5 6 7 8 9 10 11 12 #块级作用域 if 1 == 1: name= "lzl" ...

  2. python程序结构有哪几种_Python数据结构与算法(几种排序)小结

    Python数据结构与算法(几种排序) 数据结构与算法(Python) 冒泡排序 冒泡排序(英语:Bubble Sort)是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺 ...

  3. python的作用域分别有几种_python中作用域与函数嵌套

    知识回顾: 拆解传参. 1.字典传参.使用** 2.列表传参.使用* 实际上我们在定义函数的时候,如果省略了星号,那么在调用函数的时候必须要省略星号,除非我们拆解后的参数个数刚好相等. 视频内容 本节 ...

  4. python的作用域分别有几种_Python的作用域

    如果习惯了C/C++,Java这类静态语言的作用域规则,那么在Python中就要格外注意.在代码中,我们经常会碰到同一个变量名出现在多个地方,它的作用域可能是不一样的.Python中有四种作用域:局部 ...

  5. python的sort方法是哪种_python中的sort方法使用详解

    Python中的sort()方法用于数组排序,本文以实例形式对此加以详细说明: 一.基本形式列表有自己的sort方法,其对列表进行原址排序,既然是原址排序,那显然元组不可能拥有这种方法,因为元组是不可 ...

  6. python组合类型有哪三种_Python基础语法三组合数据类型

    一.列表(Lists) 列表属于Python中的序列类型,它是任意对象的有序集合,通过 " 位置 "或者 " 索引 " 访问其中的元素,它具有可变对象.可变长度 ...

  7. python基本程序结构有几种_python基础梳理(一)(推荐)

    一.python程序的组成 表达式:建立并且处理数据对象且能返回数据对象的引用关系 示例:1 + 2 系统会产生1和2俩个对象,并且进行处理生产对象3,将对象3返回回去. 二.核心的数字类型 1.整型 ...

  8. python中代理模式分为几种_Python设计模式之代理模式实例详解

    本文实例讲述了Python设计模式之代理模式.分享给大家供大家参考,具体如下: 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问 #!/usr/bin/env py ...

  9. python输入的方式有几种_Python输入方式具体的三种实现方式

    Python输入方式一个很多人都关心的问题,其实在实际中最实用的有三种输入方式.下面我们就来看看Python输入方式的具体办法.希望大家有所收获,只有这样才能更好的进行推广. 1.文件方式 将复制的代 ...

  10. python映射类型包括哪三种_Python映射类型

    映射对象用于将哈希表值映射到任意对象.在python中,有一种称为字典的映射类型.这是可变的. 字典的键是任意的.作为值,我们可以使用不同种类的元素,例如列表,整数或任何其他可变类型的对象. 一些与字 ...

最新文章

  1. 数据结构实验之图论八:欧拉回路
  2. k-Means算法(Machine Learning in Action)基于python3.6
  3. Python 俄罗斯方块, 基于pyqt5实现俄罗斯方块 --pyqt5 进阶
  4. Vue组件化之VueComponent介绍
  5. 你代码里的 ThreadLocalRandom,真的安全吗?
  6. 创建使用模块与datetime模块使用
  7. eclipse断点不能下一步_大盘下一步这样走,不能错过
  8. CacheCloud-资源归档
  9. 用java编写英寸到厘米的转换_像素、英寸、厘米的换算 - flyinglife - JavaEye技术网站...
  10. 电脑计算机无法搜索文件,电脑中的文件搜索功能出错怎么办?电脑无法搜索出实际存在的文件如何解决...
  11. adjacent_diffenerce
  12. rviz中显示Marker标记
  13. 爬取网易严选某种衣服商品数据,实现可视化,结论有点吓人
  14. Python pandas库|任凭弱水三千,我只取一瓢饮(5)
  15. 投放钻展要如何布局才能提升钻展推广的ROI
  16. 达美乐中国IPO遇挫:延迟全球发售 原计划上周上市敲钟
  17. The error occurred while setting parameters,Communications The error may involve defaultParameterMap
  18. ImageLoader 详解
  19. 码农的半衰期只有15年?
  20. 转载 centos 7 安装2080ti驱动

热门文章

  1. TFS Two Build Definations Share the Same Code Branch
  2. MVC自定义路由的配置,必须把自己的路由写在前面
  3. 初学Codesmith,第一次写模板
  4. 去掉内容中的所有全部html标签。
  5. Stylus Loader has been initialized using an options object that does not match the API schema.
  6. pl/mysql安装_PL/SQL环境安装设置
  7. mysql使用变量填值为数组_MySQL如何有效的存储IP地址?
  8. 新安装的apache无法解析php,apache无法解析php
  9. 城市轨道交通运营管理属于什么院系_青西新区高职校城市轨道交通运营与管理专业礼仪教学成果考核圆满结束...
  10. stm32f adc matlab 串口,基于Matlab和串口通信的ADC动态性能FFT测试法