Python命名空间(Namespaces)和作用域(Scopes)讲座
命名空间(Namespace)
命名空间(Namespace),是名称到对象的映射。
命名空间提供了在项目中避免名字冲突的一种方法。命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响——
不同命名空间中的名称之间绝对没有关系,请牢记这一点
。
多个名称(在多个作用域内)可以绑定到同一个对象。这在其他语言中称为别名。在处理不可变的基本类型(数字,字符串,元组)时可以安全地忽略它。但是,对于可变对象,如列表,字典和大多数其他类型在某些方面表现得像指针,如果函数修改了作为参数传递的对象,调用者将看到更改。
几个命名空间的例子:存放内置函数的集合(包含 abs() 这样的函数名,和内建的异常名称 BaseException、Exception 等等);模块中的全局名称;函数中的局部名称,包括函数的参数和函数中的变量。 从某种意义上说,对象的属性集合也是一种命名空间的形式。
命名空间查找顺序
当一行代码要使用变量 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、最后在内置命名空间中搜索
命名空间的生命周期
不同的命名空间在不同的时刻创建,有不同的生存期。
1、内置命名空间在 Python 解释器启动时创建,会一直保留,不被删除。
2、模块的全局命名空间在模块定义被读入时创建,通常模块命名空间也会一直保存到解释器退出。
3、当函数被调用时创建一个局部命名空间,当函数返回结果 或 抛出异常时,被删除。每一个递归调用的函数都拥有自己的命名空间。
作用域(Scopes)
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。