一、变量的作用域

Python的作用域一共有4种,分别是:
1、L,局部作用域
2、E,闭包函数外的函数中
3、G,全局作用域
4、B,内建作用域
L –> E –> G –>B 的规则查找,即:
在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
例如下面的代码,诠释了变量的作用域关系:

  1. #!/usr/bin/env
  2. # 内建作用域
  3. a = int(3.2)
  4. # 全局作用域
  5. b = 0
  6. def outer():
  7. # 闭包函数外的函数中
  8. c = 10
  9. # 能够打印成功
  10. print(a)
  11. def inner():
  12. # 局部作用域
  13. d = 100
  14. # 能够打印成功
  15. print(c)
  16. inner()
  17. outer()
  18. # 报错,有作用域的包含
  19. print(c)

二、全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。
例:

  1. #!/usr/bin/env
  2. # 内建作用域
  3. a = int(3.2)
  4. # 全局作用域
  5. b = 0
  6. def outer():
  7. # 闭包函数外的函数中
  8. c = 10
  9. # 能够打印成功
  10. print(a)
  11. outer()
  12. # 报错,有作用域的包含
  13. print(c)

三、global 和 nonlocal关键字

当内部作用域想修改外部作用域的变量时,就要用到globalnonlocal关键字了。
例如下面的例子,我们发现虽然能够读取到外部变量的信息,却无法修改:

  1. #!/usr/bin/env
  2. # 内建作用域
  3. a = 1
  4. def outer():
  5. # 修改外部变量
  6. a = 10
  7. # 能够打印成功
  8. print(a)
  9. outer()
  10. # 发现不能影响到外部变量
  11. print(a)

这种时候就要使用global关键字了:

  1. #!/usr/bin/env
  2. # 内建作用域
  3. a = 1
  4. def outer():
  5. global a
  6. # 修改外部变量
  7. a = 10
  8. # 能够打印成功
  9. print(a)
  10. outer()
  11. # 发现不能影响到外部变量
  12. print(a)

如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了

  1. #!/usr/bin/env
  2. a = 300
  3. def outer():
  4. a = 0
  5. def inner():
  6. nonlocal a #使用nonlocal关键字声明
  7. print(a) #输出修改之前的值
  8. a = 100 #修改a的值
  9. print(a) #输出修改后的值
  10. inner() #调用内部函数
  11. print(a) #输出调用内部函数后,外部函数中a的值
  12. outer()
  13. print(a)

四、global与nonlocal的区别

1、两者的功能不同。

global关键字修饰变量后标识该变量是全局变量,对该变量进行修改就是修改全局变量,而nonlocal关键字修饰变量后标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal位置会发生错误(最上层的函数使用nonlocal修饰变量必定会报错)。

2、两者使用的范围不同。

global关键字可以用在任何地方,包括最上层函数中和嵌套函数中,即使之前未定义该变量,global修饰后也可以直接使用,而nonlocal关键字只能用于嵌套函数中,并且外层函数中定义了相应的局部变量,否则会发生错误(见第一)。

总结:global可以在任意位置声明变量为全局变量,nonlocal只能在函数内部使用,声明变量为上级函数的局部变量。