精简解答python命名空间和作用域


文章目录

  • 精简解答python命名空间和作用域
  • 1.命名空间
  • 2.变量在命名空间的存在形式
  • 3.命名空间查找顺序
  • 4.命名空间的生命周期
  • 5.命名空间的实例


1.命名空间

简单来说,命名空间就是变量的作用域。在python中,命名空间(变量作用域)主要有三类:

  • 局部命名空间:特指当前函数或类的方法。如果函数定义了一个局部变量 x,或一个参数 x,Python 将使用它,然后停止搜索。
  • 全局命名空间:特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python 将使用它然后停止搜索。
  • 内置命名空间:对每个模块都是全局的。作为最后的尝试,Python 将假设 x 是内置函数或变量。

注意:牢记一句话:只有函数、类、模块会产生作用域,代码块不会产生作用域

2.变量在命名空间的存在形式

命名空间是一个字典的实现,变量名变量对应的值。各个命名空间是独立没有关系的,一个命名空间中不能有重名,但是不同的命名空间可以重名而没有任何影响。

3.命名空间查找顺序

当一行代码要使用变量 x 的值时,Python 会到所有可用的名字空间去查找变量,他会按照从小到大的顺序去找:局部命名空间->全局命名空间->内置命名空间,如果找到则会停止搜索。

4.命名空间的生命周期
  • 内置命名空间在 Python 解释器启动时创建,会一直保留,不被删除。
  • 模块的全局命名空间在模块定义被读入时创建,通常模块命名空间也会一直保存到解释器退出。
  • 当函数被调用时创建一个局部命名空间,当函数返回结果 或 抛出异常时,被删除。每一个递归调用的函数都拥有自己的命名空间。
5.命名空间的实例

(1)代码块不会产生作用域

if True:
    i = 1
print(i)

# 结果:1

解释:这里代码块不会产生作用域,所以,i是存在于全局命名空间{i: 1},print是位于全局空间内的代码,所以,print能找到i
再举一个例子,加深理解

def f():
    i = 1
    if i == 1:
        vol = 0
    else:
        vol = -1
    print(vol)
f()

# 结果:
0

(2)函数的作用域

def f():
    i = 1
f()
print(i)

# 结果:
NameError: name 'i' is not defined

这个例子很容易理解,不做说明
(3)创建命名空间时,python会先检查到要被赋值的代码并填充局部命名空间

i = 1
def f():
    i += 1
    print(i)
f()

# 结果:
local variable 'i' referenced before assignment

解释:由于创建命名空间时,python会检查代码并填充局部命名空间。在python运行那行代码之前,就发现了对i的赋值,并把它添加到局部命名空间中,即{i: None}。当函数执行时,python解释器认为i在局部命名空间中但没有值,所以会产生错误。
再举一个例子加深理解:

i = 1
def f():
    i
    print(i)
f()

# 结果:
1

解释:因为函数f()中没有赋值语句,所以,该局部空间内没有键值对,当执行到语句i时,因为局部命名空间里没有,所以会到全局命名空间中去找,结果找到键值对i: 1 (4)多重函数嵌套,嵌套的内部函数又是一个局部作用域.

def g():
    i += 1
    print(i)
        
def f():
    i = 2
    g()
f()

# 结果:
name 'i' is not defined

解释:错误原因和(3)中一样
再举一个例子加深印象:

def g():
    i = 1
    print(i)
        
def f():
    i = 2
    g()
f()

# 结果:
1

解释:执行到f()时,python会检查代码并填充f的局部命名空间{i: 2},执行到g()时,创建g的局部命名空间{i: 1},执行print(i)时会先从局部命名空间找起,所以结果为1 (5)用del 删除命名空间中的键值对,即删除变量

def f():
  y=1
  del y
  print(y)

f()
#错误:UnboundLocalError: local variable 'y' referenced before assignment
#去掉"del y"语句后,运行正常

(6)最后再举一个例子巩固一下:

i = 1
def f():
    i = 2
    def g():
        print(i)
    return g
 
 
func = f()
func()
print(i)

# 结果:
2
1