扫描二维码,下载手机APP
下载安卓APP箭头
客服QQ
箭头给我发消息

客服QQ:3315713922
论坛 >编程语言 >Python 的命名空间(1)

Python 的命名空间(1)

课课家iOS游客发布于 2018-05-02 09:46查看:10064

懒得扫全文的童鞋,可以直接跳到最后看总结。
我们先从一个简单的栗子说起:

栗子

a 文件中有变量 va 以及类 A,b 文件导入 a 中class A ,并打印出 A

image.png

执行 b 文件的结果为:

image.png

可以发现,虽然 b 只是导入了 a 中的 class A,但导入这个过程却执行了整个 a 文件,那么我们是否能够在 b 中访问 a 中的全局变量 va 呢:

image.png

尝试了各类调用方法,发现都无法正常访问 a 的全局变量 va,既然 b 的导入执行了整个 a 文件,甚至还打印出了 va 的 id 和值,又为什么无法在 b 中调用 va 呢?

这个问题所涉及到的内容就是:命名空间。

但在开始正题之前,我们需要阐明若干概念:

一些基本概念的澄清

对象

Python 一切皆对象,每个对象都具有 一个ID、一个类型、一个值;对象一旦建立,ID 便不会改变,可以直观的认为 ID 就是对象在内存中的地址

image.png

上例 a, b 共享了同一个 ID、同一个值、同一个类型。因此 a, b 表达的是同一个对象,但 a, b 又明显是不同的,比如一个叫 'a' 一个叫 'b'…既然是同一个对象,为什么又有不同的名字呢?难道名字不是对象的属性?

标识符

事实确实如此,这是 Python 比较特殊一点:如同'a' 'b' 这样的名称其实有一个共同的名字:identifier(注意不要与 ID 混淆了),中文名为“标识符”,来解释一下:

标识符:各类对象的名称,比如函数名、方法名、类名,变量名、常量名等。

在 Python 中赋值并不会直接复制数据,而只是将名称绑定到对象,对象本身是不知道也不需要关心(该关心这个的是程序猿)自己叫什么名字的。一个对象甚至可以指向不同的标识符,上例中的'a' 'b'便是如此。真正管理这些名子的事物就是本文的主角”命名空间” 。

命名空间

命名空间:(英语:Namespace)表示标识符(identifier)的可见范围。(ps:copy 自 SF)

简而言之,命名空间可以被简单的理解为:存放和使用对象名字的抽象空间

作用域

与命名空间相对的一个概念就是“作用域”,那么什么又是作用域呢?

作用域:(英文 Scope)是可以直接访问到命名空间的文本区域。

这里需要搞清楚什么是直接访问:

image.png

image.png

Python 中不加 . 的访问为直接访问,反之为属性访问。
因此作用域必定是相对某个对象内部而言的,比如一个函数内部、一个模块全局等,那作用域和命名空间是什么关系呢:

  1. 作用域是一种特殊的命名空间,该空间内的名称可以被直接访问;

  2. 并不是所有的命名空间都是作用域。

看不懂? 没关系,后面会解释,我们先回到命名空间这个话题上:

现今 Python 的大部分命名空间是通过字典来实现的,也即一个命名空间就是名字到对象的映射。另外, Python 允许对命名空间进行嵌套,而我们经常接触的命名空间有四层:

LEGB 规则

LEGB 层级

这四层命名空间可以简记为 LEGB:

  1. 局部命名空间(local):指的是一个函数所定义的空间或者一个类的所有属性所在的空间,但需注意的是函数的局部命名空间是一个作用域,而类的局部命名空间不是作用域。

  2. 闭包命名空间(enclosing function): 的作用域(Python 3 引入)。

  3. 全局命名空间(global):读入一个模块(也即一个.py文档)后产生的作用域。

  4. 内建命名空间(builtin):Python 解释器启动时自动载入__built__模块后所形成的名字空间;诸如 str/list/dict…等内置对象的名称就处于这里。

为了说清楚这几层洋葱皮,举个栗子:

image.png

内建命名空间比较好理解,我们重点讲解下其他三个:

  1. 'v1' 为全局变量 v1 的名子,其所处的命名空间为全局命名空间;需要注意的是全局命名空间包括 'func' 但不包括 func 的作用域。

  2. func 内部囊括 'v2' 和 'inn_func' 名称的空间为局部命名空间;

  3. 执行 func 后,func 的作用域释放(或许遗忘更合适),并返回了绑定了 v 和 v2 变量的闭包函数 inn_func,此时闭包所具有的作用域为闭包空间,因此局部命名空间和闭包命名空间是相对而言的,对于父函数 func 而言,两者具有产生时间上的差异。

LEGB 访问规则

搞清楚各个层级概念后,我们来说一下 LEGB 的访问规则: 同样的标识符在各层命名空间中可以被重复使用而不会发生冲突,但 Python 寻找一个标识符的过程总是从当前层开始逐层往上找,直到首次找到这个标识符为止

image.png

image.png

上例中,全局变量和函数 f 都定义了 变量 v1,结果 Python 会优先选择 f 的局部变量 v1 ,对于 f 内并未定义的变量 v2 ,Python 会向上搜寻全局命名空间,读取全局变量 v2 后打印输出。

收藏(0)0
查看评分情况

全部评分

此主贴暂时没有点赞评分

总计:0

回复分享

版主推荐

    共有0条评论

      • 课课家运营团队
      • Mr ken
      • YUI
      • cappuccino
      • mr jack
      • IT宅男
      • Mright
      • 课课家技术团队1
      • 选择版块:

      • 标题:

      • 内容

      • 验证码:

      • 标题:

      • 内容

      • 选择版块:

      移动帖子x

      移动到: