名称空间

存放名字与对象映射/绑定关系的地方变就叫名称空间,就好比变量名与变量值

内建名称空间

python 解释器提前定义好的 例如:print() len()

周期:python解释器运行则产生,python解释器关闭则销毁

全局名称空间

py文件中编写的代码运行产生的名字都会存到全局名称空间

周期:py文件开始运行则产生,py文件运行结束则销毁

  1. name = 'kevin' # 变量名name存入全局名称空间
  2. def index(): # 函数名index存入全局名称空间
  3. pass
  4. if True:
  5. a = 1 # 变量名a存入全局名称空间
  6. for i in range(10) # 变量名i存入全局名称空间
  7. pass
  8. while True:
  9. b = 2 # 变量名b存入全局名称空间

局部名称空间

函数的形参、函数内定义的名字都会被存放到局部名称空间

周期:函数体代码开始运行则产生,函数体代码运行结束则销毁

  1. def index_1():
  2. c = 1 # 变量名c存入局部名称空间

作用域

作用域就是名称空间能够作用的范围

全局作用域

全局名称空间和内建名称空间中,“名字”属于全局范围。该范围内的“名字”全局有效(除非被删除),在任意位置都可以使用

  1. a = 1 # 全局作用域的变量名a
  2. def index():
  3. print(a)
  4. index() # 结果输出全局作用域的变量名a
  5. # 1

局部作用域

局部名称空间中,“名字”属于局部范围。该范围内的“名字”(在函数调用时生成,函数调用结束后释放)局部有效(只能在函数内使用)

  1. a = 1 # 全局作用域的变量名a
  2. def index():
  3. a = 10 # 局部作用域的变量名a
  4. print(a) # 在局部找变量名a
  5. index() # 结果输出局部作用域的变量名
  6. # 10
  7. print(a) # 结果输出全局作用域的变量名a
  8. # 1

global与nonlocal关键字

global关键字

若要在函数内修改全局名称空间中“名字”的值,当值为不可变类型时,则需要添加global关键字

若值可变类型,则不需要

  1. a = 1
  2. def index_1():
  3. global a # 声明修改的是全局a,而不是产生新的a
  4. a = 10
  5. index_1()
  6. print(a)
  7. # 10

nonlocal关键字

若嵌套多层函数时,内层函数想要修外层函数局部名称空间中“名字”的值,可以使用nonlocal关键字(非全局)

  1. a = 10
  2. def index_2():
  3. a = 1 # 1.声明局部变量a
  4. def index_3():
  5. nonlocal a # 3.声明修改的是外层局部作用域a,而不是产生新的a
  6. a = 2 # 4.将值2重新赋值给a
  7. index_3() # 2.调用index_3()
  8. print(a) # 5.此时index_2()代码块中变量a被index_3()重新赋值2
  9. index_2() # 1. 调用index_2()函数
  10. # 2
  11. print(a)
  12. # 10

作用域优先级

全局作用域优先级

在全局作用域查找“名字”时,起始位置是全局作用域,所以先查找全局名称空间,没有找到,再查找内置名称空间,最后都没有找到就会抛出异常

局部作用域优先级

在局部作用域查找“名字”时,起始位置是局部作用域,所以先查找局部名称空间,没有找到,再去全局作用域查找,再查找内置名称空间,最后都没有找到就会抛出异常

补充

可以调用内建函数locals()globals()来分别查看局部作用域和全局作用域的“名字”,查看的结果都是字典格式。在全局作用域查看到的locals()的结果等于globals()