python 全局变量 global 和 nonlocal

两个关键词都用于允许在一个局部作用域中使用外层的变量。

  • global 表示将变量声明为全局变量
  • nonlocal 表示将变量声明为外层变量(外层函数的局部变量,而且不能是全局变量)
  • python引用变量的顺序如下:
  1. 当前作用域局部变量
  2. 外层作用域变量
  3. 当前模块中的全局变量
  4. python内置变量

比如:

a=1
def test(x):
   global x
   a=x
因为a外层变量是全局变量,所以要加global


def test2():
  a=1
  def test(x)
     nonlocal x
     a=x
因为a外层变量不是是全局变量,也是一个外层的局部变量,所以要加nonlocal

python 在新建一个变量时,默认作用域为当前局部作用域。如果不声明global or nonglocal,就认为是一个局部变量。

内部函数,不修改外层变量可以访问外层变量。

a = 1
def fun():
    print(a) # 在函数内部找不到对 a 的定义,则去外层查询。输出1。
fun()

内部函数,修改同名外层变量,则python会认为是定义了一个新的局部变量,与外层变量无关了。

a = 1
def fun():
a = 2 # 声明了一个局部变量,与外面等于1的那个a没有关系了
print(a) # 输出2
fun()
print(a) # 输出1

在内部函数修改同名全局变量之前调用变量名称,则引发Unbound-LocalError

a = 1
def fun():
    print(a) # 先引用
    a = 2 # 再修改
fun()

如果我们想要强制访问外层变量 a,便可以使用 global 关键字

a = 1
def fun():
    global a # a为全局变量
    print(a) # 输出1
    a = 2 # 改变的是全局变量,因此出了这个局部作用域,仍然有效
fun()
print(a) # 输出2
注意,这个时候,不要将 global 换为 nonlocal 关键字,不然会报错:

这是因为 nonlocal 表示外层变量,但是一旦外层变量是全局变量,则只能用 global。如果将这段代码全部放到一个函数中,则可以使用 nonlocal :

def outer_fun():
a = 1
def fun():
nonlocal a # a为外层变量
print(a) # 输出1
a = 2
fun()
print(a) #输出2
outer_fun()

注意:可以发现,之前的将 global 换为 nonlocal 的报错,和这次的将 nonlocal 改为 global 的报错,错误类型是不同的。前者是 nonlocal a 这一行报错,后者是 print(a) 这一行报错。也就是说,在使用 nonlocal a 之前,必须保证外层的确已经定义过 a 了,但是在 global a 的时候,可以允许全局变量中还没有定义过a,可以留在后面定义。比如将 print(a) 之前加上对a的定义,便不会出错:

def outer_fun():
a = 1
def fun():
global a # a为全局变量,与上面等于1的 a 没有关系
a = 3 # 定义全局变量
print(a) # 输出3
a = 2
fun()
print(a) #输出1,局部变量
outer_fun()
print(a) # 输出2,全局变量

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注