• python 的全局变量和局部变量


    首先我们看一段代码,是不是有很多疑惑

    def scope_test():
        def do_local():
            spam = "local spam"
    
        def do_nonlocal():
            nonlocal spam
            spam = "nonlocal spam"
    
        def do_global():
            global spam
            spam = "global spam"
    
        spam = "test spam"
        do_local()
        print("After local assignment:", spam)
        do_nonlocal()
        print("After nonlocal assignment:", spam)
        do_global()
        print("After global assignment:", spam)
    
    scope_test()
    print("In global scope:", spam)
    
    '''
    输出:
    After local assignment: test spam
    After nonlocal assignment: nonlocal spam
    After global assignment: nonlocal spam
    In global scope: global spam
    '''

    一直看不明白第三个为什么时这样,补充一下

    x = 0
    def outer():
        x = 1
        def inner():
            global x
            x = 2
            print("inner:", x)
    
        inner()
        print("outer:", x)
    
    outer()
    print("global:", x)
    
    # inner: 2
    # outer: 1
    # global: 2

    我们忘记了,如果局部变量与全局变量变量名一样,则优先调用局部变量,因此上面的难题解决了

    首先我们先了解全局变量和局部变量

    1.全局变量和局部变量的区别在于作用域,全局变量在整个py文件中声明,全局范围内可以使用;局部变量是在某个函数内部声明的,只能在函数内部使用,如果超出使用范围(函数外部),则会报错

    A = 100 # 全局变量一般用大写字母表示
    def func():
        a = 50 # 局部变量一般用小写字母表示
        print(a+A)
    
    func()  #150
    print(A)  #100
    print(a) # 报错信息NameError: name 'a' is not defined,说明局部变量只能在函数内使用

    2.在函数内部,如果局部变量与全局变量变量名一样,则优先调用局部变量

    A = 100
    def func():
        A=250
        print(A)
    
    
    print(A)    # 打印全部变量  100
    func()      # 局部变量  250

    3.如果想在函数内部改变全局变量,需要在前面加上global关键字,在执行函数之后,全局变量值也会改变

    A = 100
    
    def func():
        global  A
        A = 200
        print(A)
    
    
    print(A)    # 打印全局变量 100
    func()      # 局部变量  200
    print(A)   # 改变后的全局变量  200

    4.如果全局变量是列表类型(针对全局变量如果是可变对象,可以对内部元素进行操作),可以通过list的列表方法去对列表进行修改,并且可以不用global来声明

    list_1 = [1,2,56,"list"]
    
    def changeList():
        list_1.append("over")
        print(list_1)
    
    changeList()  #[1, 2, 56, 'list', 'over']
    print(list_1)  #[1, 2, 56, 'list', 'over']

    5.如果函数中有global关键字,变量本质上就是全局变量,可读取可赋值

    NAME = "nicholas"
    print(1,NAME)
    def change_NAME():
        global NAME
        NAME = "niubi"
        print("change_NAME", NAME)
    change_NAME()
    print(2,NAME)  #有global,定义的就是全局变量,可以赋值以及修改

    要注意global的位置,如果需要global对全局变量进行修改这里的global不能放在name = "nick"下面

    6.如果全局变量是不可变对象(非list)等,我们就不能在函数里面去修改全局变量,但是我们想修改,那么就可以使用global

    count = 0
    def global_test():
        count += 1
        print(count)
    global_test()  #UnboundLocalError: local variable 'count' referenced before assignment

    nonlocal

    python变量引用顺序:从当前作用域开始寻找变量,如果没找到就往上一层作用域寻找,没找到就再上一层......

    即:当前作用域局部变量->外层作用域变量->再外层作用域变量->......->当前模块全局变量->pyhton内置变量

    global:全局变量

    nonlocal:外层嵌套函数的变量

    使用总结:

    1、局部作用域改变全局变量用global, global同时还可以定义新的全局变量

    2、内层函数改变外层函数变量用nonlocal, nonlocal不能定义新的外层函数变量,只能改变已有的外层函数变量(外层直到全局作用域的下一层都没有,会报错),同时nonlocal不能改变全局变量

    当没有nonlocal时

    a = 10  # a1 当前模块全局变量
    def outer():
        a = 9  # a2 当前outter作用域局部变量
        def inner():
            a = 8  # a3 当前inner作用域局部变量
            print(a)  # a3 8, 在inner的局部作用域中找到了a3
        inner()  # inner()函数结束,a3作为inner局部变量被释放
        print(a)  # a2 9,在outer局部作用域中找到a2
    outer()  # outer()函数结束,a2作为outer局部变量被释放
    a
    '''
    8
    9
    10
    '''

    用于在内层函数中改变外层函数变量

    a = 10  # a1 当前模块全局变量
    def outer():
        a = 9 # a2 outer局部变量
        def inner():
            nonlocal a
            a = 8  # a3  既是inner局部变量,又是外层outer局部变量
            print(a)  # a3 8,在inner的局部作用域中找到了a3
        inner()  # inner()函数结束,a3作为外层变量(outer局部变量)被保留成为a2
        print(a)  # a2 8,在outer局部作用域中找到a2(在inner中被改变)
    outer()  # outer()函数结束,a2作为outer局部变量被释放
    print(a)  # a1 10,在当前模块全局作用域中找到了a1
    
    '''
    输出
    8
    8
    10
    '''

    如果在外层没有找到变量a,则会继续在再外层寻找,直到全局作用域的下一层为止

    a = 10  # a1 当前模块全局变量
    def outer2():
        a = 9 # a2 outer2作用域局部变量
        print(a) # a2 9,还未被a3改变
        def outer1():
            print(a) # a2 9,在outer1中没找到局部变量a,则寻找外层(outer2)变量a2(还未被a3改变)
            def inner():
                nonlocal a
                a = 0  # a3 既是inner局部变量,又是再外层outer2作用域变量
                print(a)  # a3 0, 找到inner局部变量a3
            inner()  # inner()函数结束,a3作为外层变量(outer2局部变量)被保留成为a2
            print(a)  # a2 0,在outer1中没找到局部变量a,则寻找外层(outer2)变量a2(被a3改变)
        outer1()
        print(a) # a2 0, 在outer1中找到outer1局部变量a2(被a3改变)
    outer2() 
    print(a)  # a1 10,在当前模块全局作用域中找到了a1
    
    '''
    输出
    9
    9
    0
    0
    0
    10
    '''

    全局变量不是外层变量,不被nonlocal寻找

    a = 10  # a1 当前模块全局变量
    def outer():
        def inner():
            nonlocal a  # 在当前作用域外层即outer局部作用域中没找到outer局部变量a,outer外层为全局作用域,nonlocal不继续寻找,报错
            a = 8
            print(a)
        inner()
        print(a)
    outer() 
    print(a)  # a1 10,在当前模块全局作用域中找到了a1
    
    '''
    输出
    SyntaxError: no binding for nonlocal 'a' found
    '''

    注意:使用global关键字修饰的变量之前可以并不存在,而使用nonlocal关键字修饰的变量在嵌套作用域中必须已经存在

  • 相关阅读:
    C++ 使用老牌库xzip & unzip对文件进行压缩解压
    第一次玩蛇,有点紧张。
    fiddler 抓取手机http/https包
    disk或者Partition镜像的制作
    VS2013+phread.h环境配置
    C++ 浅谈 strlen 与 sizeof的区别
    Qt 显示网页的控件
    Qt error: C2236: 意外的标记“class”。是否忘记了“;”?
    初识MySQL——人生若如初相逢
    【学习笔记】HTML基础:列表、表格与媒体元素
  • 原文地址:https://www.cnblogs.com/cgmcoding/p/14204285.html
Copyright © 2020-2023  润新知