# 一、名称空间(Namespace)
名称空间(namespace):一种代码组织的形式,通过命名空间来分类,区别不同的代码功能,避免不同的代码片段(通常由不同的人协同工作或调用已有的代码片段)同时使用时由于不同代码间变量名相同而造成冲突。 命名空间是用来组织和重用代码的。
## 内置名称空间(Built-in Namespace)
内置命名空间会在python解释器启动的时候就会创建,所以可以在启动python的位置随时调用,当python结束运行的时候会释放内置命名空间
比如在内置空间中的有 print()、len()、ValueError 等。
## 全局名称空间(Global Namespace)
全局命名空间是在python模块中(python文件中)创建的变量名或是函数,全局名称的存活时间是程序开始至程序结束。模块加载时创建包含模块级别的变量、函数、类等。生命周期与模块一致。
只要不是函数内部定义的(包含函数的参数)那就是不是内置的变量名和局部变量名
```python# -*- coding: utf-8 -*-'''@File : 9-名称空间@Author : HY @Version : 1.0@Desc : None'''x=100def func(): x=10print(x)'''@OutPut : 100'''```
在这个例子中打印的就是全局名称空间的x
## 局部名称空间(Local Namespace)
函数调用时创建。包含函数内部定义的变量和参数。函数执行完毕后销毁。
```python# -*- coding: utf-8 -*-'''@File : 9-名称空间@Author : HY @Version : 1.0@Desc : None'''x=100def func(): x=10 print("局部变量%s"%(x))func()print(f"全局变量{x}")print("全局变量{}".format(x))'''@OutPut : 局部变量10全局变量100全局变量100'''```
## 类命名空间(Class Namespace)
类定义时创建,存储类属性和方法。实例命名空间则保存实例的属性。类的命名空间在类定义时生成,并且可以通过类名直接访问其中的属性和方法。每个类都拥有自己的命名空间,而类的实例则拥有自己的实例命名空间。
```python# -*- coding: utf-8 -*-'''@File : 9-名称空间@Author : HY @Version : 1.0@Desc : None'''class MyClass: class_var = 100 # 类变量,属于类命名空间 def __init__(self): self.instance_var = 200 # 实例变量,属于实例命名空间 def class_method(): print("这是一个类方法")# 创建类的实例obj = MyClass()# 访问类命名空间中的变量print(MyClass.class_var) # 输出: 100# 访问类命名空间中的方法MyClass.class_method() # 输出: 这是一个类方法# 访问实例命名空间中的变量print(obj.instance_var) # 输出: 200'''@OutPut : 100这是一个类方法200'''```
**总结:命名空间的作用在于避免不同上下文中同名标识符之间的冲突,确保每个名字只指向它所属的特定对象。**
# 二、作用域(Scope)
作用域是指变量或函数在程序中可以被访问的区域。它决定了在代码的哪些部分可以使用某个变量名。
Python 中的作用域类型:
## 局部作用域(Local Scope):
函数内部定义的变量属于局部作用域。只能在函数内部访问。若函数中对变量赋值,则默认为局部变量,即使外部有同名全局变量也不会影响全局变量。
## 封闭作用域(Enclosing Scope):
嵌套函数中,外层函数的作用域称为封闭作用域。内层函数可以访问外层函数中的变量。使用 nonlocal 关键字可以修改外层函数中的变量。
## 全局作用域(Global Scope):
模块顶层定义的变量属于全局作用域。可在整个模块中访问。使用 global 关键字可以在函数内部修改全局变量。
## 内置作用域(Built-in Scope):
Python 内置函数和异常所在的命名空间。所有变量都可直接访问,无需导入。
# 三、LEGB 规则
Python 查找变量名时遵循 LEGB 规则:
L (Local):首先在当前函数的局部作用域中查找。
E (Enclosing):如果未找到,则在包含当前函数的外层函数的作用域中查找。
G (Global):如果仍未找到,则在全局作用域中查找。
B (Built-in):最后在内置作用域中查找。
这个规则确保了变量的查找顺序清晰且可预测。
# 四、命名空间与作用域的关系
每个作用域都有一个对应的命名空间。
局部作用域 → 局部命名空间
全局作用域 → 全局命名空间
封闭作用域 → 封闭命名空间
内置作用域 → 内置命名空间
作用域和名称空间的查找优先级是:局部命名空间>封闭命名空间>全局命名空间>内置命名空间。
名称空间的查找顺序不是以调用阶段为基准的而是以定阶段为基准的。
```python# -*- coding: utf-8 -*-'''@File : 9-名称空间@Author : HY @Version : 1.0@Desc : None'''def outer_function(): x = 10 # 局部变量 def inner_function(): print(x) # 这里访问的是outer_function中的x return inner_function# 在定义阶段,inner_function已经确定了它要访问的x来自outer_functionfunc = outer_function()func() # 输出: 10'''@OutPut : 10'''# -*- coding: utf-8 -*-'''@File : 9-名称空间@Author : HY @Version : 1.0@Desc : None'''def outer_function(): x = 10 # 局部变量 def inner_function(): print(x) # 这里访问的是outer_function中的x x=100 #这样这里就会报错,因为语法是没有问题的所以不会在运行之前给出提示,只有当程序运行的时候才会出现UnboundLocalError return inner_function# 在定义阶段,inner_function已经确定了它要访问的x来自outer_functionfunc = outer_function()func() # 输出: 10'''@OutPut : print(x) # 这里访问的是outer_function中的xUnboundLocalError: local variable 'x' referenced before assignment'''```
命名空间是变量存储的地方,而作用域是变量可以被访问的区域。
作用域是静态确定的,但运行时会动态地根据调用栈决定当前活跃的命名空间。
五、示例说明
```pythonx = "global" # 全局变量def outer(): x = "enclosing" # 封闭变量 def inner(): x = "local" # 局部变量 print(x) # 输出 local inner() print(x) # 输出 enclosingouter()print(x) # 输出 global```
在这个例子中:
x 的作用域从内到外依次是:局部 → 封闭 → 全局 → 内置。
Python 查找变量 x 时,按照 LEGB 规则进行搜索。
六、关键点总结
通过合理使用命名空间和作用域,我们可以更好地组织代码结构,防止命名冲突,并提高程序的可维护性和可读性。