global
表示不再使用局部局部作用域中的内容,而是改用全局作用域中的变量
1 a = 100 2 3 4 def func(): 5 global a # 表示不再局部创建这个变量,而是直接使用这个全局的a 6 a = 28 7 print(a) 8 9 10 func() 11 print(a)
执行结果
28
28
Process finished with exit code 0
对于可变的数据类型如列表、字典等也可以使用global
1 lst = [1, 2, 3] 2 dic = {1: 1, 2: 2} 3 4 5 def func(): 6 global lst 7 global dic 8 lst = [2, 3, 4] 9 dic = {1: 10, 2: 20} 10 print(lst) 11 print(dic) 12 13 14 func() 15 print(lst) 16 print(dic)
执行结果
[2, 3, 4] {1: 10, 2: 20} [2, 3, 4] {1: 10, 2: 20} Process finished with exit code 0
对于可变数据类型,如果不加global,那么可以追加元素,删除元素,修改元素,但是不能直接赋值(就是不能 lst =[....]),直接赋值的结果是创建一个局部的列表或字典
1 lst = ["麻花疼", "刘强东", "雷军军"] 2 dic = {"马云": "淘宝"} 3 4 5 def func(): 6 lst.append("马云云") 7 # lst = ["马化腾", "雷军"] 8 lst.remove("刘强东") 9 dic["强东"] = "京东" 10 dic["马云"] = "支付宝" 11 print(lst) 12 print(dic) 13 14 15 func() 16 print(lst) 17 print(dic)
执行结果
['麻花疼', '雷军军', '马云云'] {'马云': '支付宝', '强东': '京东'} ['麻花疼', '雷军军', '马云云'] {'马云': '支付宝', '强东': '京东'} Process finished with exit code 0
如果在函数里面直接赋值,结果会是怎么样的呢,来看代码
1 lst = ["麻花疼", "刘强东", "雷军军"] 2 dic = {"马云": "淘宝"} 3 4 5 def func(): 6 # lst.append("马云云") 7 lst = ["马化腾", "雷军"] # 相当于在局部名称空间重新创建一个变量lst指向新列表[...] 8 # lst.remove("刘强东") 9 dic["强东"] = "京东" # 直接对全局名称空间的dic进行修改 10 # dic["马云"] = "支付宝" 11 print(lst) 12 print(dic) 13 14 15 func() 16 print(lst) 17 print(dic)
执行结果
['马化腾', '雷军'] {'马云': '淘宝', '强东': '京东'} ['麻花疼', '刘强东', '雷军军'] {'马云': '淘宝', '强东': '京东'} Process finished with exit code 0
nonlocal
nonlocal表示在局部作用域内,调用父级命名空间中的变量
1 a = 10 2 3 4 def func1(): 5 a = 20 # 局部变量 6 7 def func2(): 8 # nonlocal a # 调用func1里面的a(值为20) 9 a = 30 # 将func1里面a的值改为30 10 print(a) # 打印30 11 12 func2() 13 print(a) # func1里面a的值已经改为30了,因此打印30,不加nonlocal打印20 14 15 16 func1() 17 print(a) # 打印全局变量a(值为10)
执行结果
30
30
10
Process finished with exit code 0
综合运用
来看一段代码
a = 1 def func1(): a = 2 def func2(): nonlocal a a = 3 def func3(): a = 4 print(a) print(a) func3() print(a) print(a) func2() print(a) print(a) func1() print(a)
运行结果
1
2
3
4
3
3
1
Process finished with exit code 0
来看分析,注意执行顺序,从上往下,遇到函数定义跳过,遇到函数调用时跳转到函数定义,函数体执行完接着之前的位置执行。
a = 1 # 创建全局变量a(值为1) def func1(): a = 2 # 创建局部变量a def func2(): nonlocal a # 调用func1(父级命名空间)里面的a a = 3 # 把func1里面a的值改为3 def func3(): a = 4 # 创建局部变量a print(a) # 打印func3里面局部变量a的值4-----4 print(a) # 打印func2里面的a的值3------3 func3() print(a) # 打印func2里面的a的值3(func3里面的a不影响func2的a)------5 print(a) # 打印func1里的局部变量a的值2------2 func2() print(a) # 打印func1里面的a的值3(func1里面的a已经被func2改成了3)-------6 print(a) # 打印全局变量a的值1------------1 func1() # 跳转到func1定义的位置 print(a) # 打印1---------7
总结
(1)调用变量是要搞清楚变量是全局变量还是局部变量,如果是局部变量的话是属于哪个函数的,它能否被其子函数调用
(2)注意代码的执行顺序,代码从上往下执行,遇到函数定义跳过,等到遇到函数调用时才跳转到定义的部分开始执行,执行完了后再跳转到函数调用的地方