函数的作用域、global与nonlocal

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)注意代码的执行顺序,代码从上往下执行,遇到函数定义跳过,等到遇到函数调用时才跳转到定义的部分开始执行,执行完了后再跳转到函数调用的地方

 

posted @ 2018-12-22 17:29  乘月归  阅读(291)  评论(0编辑  收藏  举报