您不知道的Python中global、nonlocal哪些事儿

Python中全局变量、局部变量以及global、nonlocal关键字的用法

1.全局变量和局部变量

前言:

  • 全局变量是在整个py文件中声明,全局范围内都可以访问;
  • 局部变量是在某个函数中声明的,只能在该函数中调用它,如果试图在超出范围的地方调用,程序就爆掉了
  • 如果在函数内部定义与某个全局变量一样名称的局部变量,就可能会导致意外的效果,可能不是你期望的。因此不建议这样使用,这样会使得程序很不健全。

有 4 条法则,来区分一个变量是处于局部作用域还是全局作用域:

  1. 如果变量在全局作用域中使用(即在所用函数之外),它就总是全局变量。
  2. 如果在一个函数中,有针对该变量的 global 语句,它就是全局变量。
  3. 否则,如果该变量用于函数中的赋值语句,它就是局部变量。
  4. 但是,如果该变量没用用在赋值语句中,它就是全局变量。

阅读 例1,可以更好地理解这些法则,

# 例 1
def test1():
    global str1
    str1 = 'hello' # 这是全局变量
def test2():
    str1 = 'python' # 这是局部变量
def test3():
    print(str1) # 这是全局变量
str1 = 42   # 这是全局变量
test1()
print(str1) # out: hello

解释:在 test1() 函数中,str1 是全局 str1 变量,因为在函数的开始处,有针对 str1 变量的 global 语句。在 test2() 函数中,str1 是局部变量,因为在该函数中有针对它的赋值语句。在 test3() 函数中,str1 是全局变量,因为在这个函数中,既没有赋值语句,也没有针对它的 global 语句。

  • 在一个函数中,一个变量要么总是局部变量,要么总是全局变量。函数中的代码没有办法先使用名为 str1 的局部变量,稍后又在同一个函数中使用全局变量。
  • 如果想在一个函数中修改全局变量中存储的值,就必须对该变量使用 global 语句。
  • 在一个函数中,如果试图在局部变量赋值之前就使用它,Python就会报错。如例2
#例 2
def test1():
	print(str1) # ERROR
	str1 = 'hello world' # 局部变量
str1 = 'hi' # 全局变量
test1()
'''
报错:
File "E:/test/test.py", line 92, in test1
    print(str1) # ERROR
UnboundLocalError: local variable 'str1' referenced before assignment
'''

例2解释:之所以报错,因为 Python 看到 test1() 函数中有针对 str1 的赋值语句,所以会认为 str1 变量是局部变量。但是 print(str1) 语句的执行在 str1 赋值之前,局部变量 str1 并不存在(即赋值之前应用本地变量 str1)。Python不会退回使用全局 str1 变量。

2. global语句

使用 global 语句可以在一个函数内修改全局变量。如果在函数内的顶部有 " global str1 "这样的代码,它就告诉 Python ,“在这个函数中,str1 指的是全局变量,所以不要用这个名字创建一个局部变量”。例如下面代码:

def test1():
	global str1
	str1 = 'one'
str1 = 'global'
test1()
print(str1) # out: one

因为 str1 在 test1() 的顶部被声明 gloabl,所以当 str1 被赋值为 ‘one’ 时,赋值发生在全局作用域的 str1 上。没有创建局部 str1 变量。

3. nonlocal语句

Python 3.0 引入了一条新的nonlocal语句,实际上,当执行到 nonlocal 语句的时候,nonlocal中列出的名称必须在一个嵌套的def中提前定义过,否则,将会产生一个错误。nonlocal名称只能出现在嵌套的def中,而不能在模块的全局作用域中或def之外的内置作用域中。
表示在局部作用域中,调用父级作用域中的变量;如果嵌套了很多层,最多只能作用到最顶层的函数,不能作用于全局变量。
在这里插入图片描述
在这里插入图片描述
动手算算这些题,理论要和实际相结合

a = 1
def func_1():
    a =2
    def func_2():
        # a = 3  #模块A
        def func_3():
            nonlocal a
            a = 4
            print(' 8行:',a)
        print(' 9行:',a)
        func_3()
        print('11行:',a)#2 --> 4
    print('12行:',a)
    func_2()
    print('14行:',a)#2-->4
print('15行:',a)
func_1()
print('17行:',a)#全局变量,nonlocal无权更改

上面代码中,加上模块A的结果:
在这里插入图片描述
不加模块A的结果:
在这里插入图片描述

发布了41 篇原创文章 · 获赞 49 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/wls666/article/details/96721734