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

  • 相关阅读:
    Java 利用SWFUpload多文件上传 session 为空失效,不能验证的问题 swfUpload多文件上传
    对ExtJS4应用 性能优化的几点建议
    Extjs4中用combox做下拉带图片的下拉框
    当你的才华还撑不起你的野心时,就应该静下心来学习(转)
    占位符行为 PlaceHolderBehavior 的实现以及使用
    一个简单的TabItem样式。
    WPF实现Twitter按钮效果(转)
    模仿36。杀毒~button(转)
    WPF自适应可关闭的TabControl 类似浏览器的标签页(转)
    WPF绘制简单常用的Path(转)
  • 原文地址:https://www.cnblogs.com/zzliu/p/10161791.html
Copyright © 2011-2022 走看看