Python/作用域与名字空间

变量的作用域共有4种:

  • L (Local) 局部作用域
  • E (Enclosing) 外层非全局的闭包作用域
  • G (Global) 全局作用域
  • B (Built-in) 内建作用域

按照L –> E –> G –>B 的顺序查找变量。

Python 中只有模块(module)、类(class)、函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)不会引入新的作用域,这些语句内定义的变量,在语句的外部也可以访问。

类与函数可以闭包(enclosing)。如果在一个内部函数里,对一个外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被称为闭包(closure),而这个被内部函数引用的变量则被成为自由变量

global关键字指明要访问全局的变量。nonlocal关键字指明要访问外层非全局作用域的变量。在函数作用域内部,可以读访问全局变量,但如果修改则自动被当作是一个同名的局部变量,除非显式使用global关键字。如:

list1 = []
def test3():
   list1 = [2]

nonlocal是从Python 3.0引入的关键字,允许赋值修改外层非全局的变量。

从Python解释器的实现看,维持全局名字字典与局部名字字典,可以分别用globals()与locals()列出两个作用域内的全部名字。对于类或对象实例,还可以用vars(InstanceName)访问其类或实例作用域内的名字。注意,locals()的值只能读不能修改。