python高阶教程-命名空间与作用域

  • 2019 年 11 月 20 日
  • 筆記

本篇内容来自原创小册子《python高阶教程》,点击查看目录

问题引入

文件1内容如下:

文件2内容如下:

如果我们运行文件2,结果会是什么呢?

可以看到,文件2中的from file_one import file_one_var1语句执行后,文件1中的内容立即全部执行,所以输出了file one is running。接着在文件2中输出了file_one_var1的值,但是输出file_one_var2时报错。

问题在于,明明文件1中的所有语句都执行过了,为什么file_one_var2无法在文件2中使用?这涉及到python的命名空间与作用域问题。

名词解释

  • 命名空间

命名空间(Namespace):名字(标识符)到对象的映射。

简而言之,命名空间可以理解为:记录对象和对象名字对应关系的空间;现今 python 的大部分命名空间是通过字典来实现的, 也即一个命名空间就是名字到对象的映射,标识符是键,对象则是值。

  • 作用域

作用域(Scope):本质是一块文本区域, Python 通过该文本区域可以直接访问相应的命名空间。

直接访问是指通过名字访问,如print(a)对a是直接访问;属性访 问指的是通过点号访问,如print(a.A)对A是属性访问。

python的作用域

  • 四种作用域
  • LEGB法则
  • 特殊关键字
    • global 可以允许修改全局变量
    • nonlocal 将变量的命名空间由enclosing引入local

类的命名空间

待增补。

练习

这里c是模块里的全局变量,在bar函数中试图对全局变量进行修改,但是执行完bar函数后打印c,发现还是global,修改失败。可以看到,这里在global域和local域各有一个对象c,对全局变量的修改不可行。

这里使用global关键字声明了全局变量,修改成功。注意global关键字并没有把c引入local域,因为打印locals()函数发现local域没有对象。

定义了嵌套函数foo_in(), 对foo_in()来说,foo()的作用域为enclosing。这里试图直接在local域使用enclosing域的对象,但是报错。

使用关键词nonlocal后,可以在local域使用enclosing域的对象,并且nonlocal可以把enclosing域的对象引入local域,因为打印locals()后发现命名空间里有a