python global 与 nonlocal

global 关键字

定义在main函数或者外部的变量是全局变量,我们可以访问,但是如果需要求改则需要使用改关键词.
即如果需要在局部域修改全局变量,则需要需要使用global关键字再次声明

def scope():
    global a, t  # 否则不能修改
    a += 1
    t += 'yy'
    print(a, t, g)

if __name__ == '__main__':
    a = 0
    t = 'sss'
    g = [1, 2, 3]
    scope()
1 sssyy [1, 2, 3]

否则如下则修改失败

a = 'init...'

def scope():
    a = 'change..'

if __name__ == '__main__':
    scope()
    print(a)
init...

nonlocal 关键字

简单说,该关键字用在嵌套函数中,可以用来改变一个变量的作用域,即在本不是该局部域的变量作用域的地方,继续使用该变量
如下,如果没有使用nonlocal 关键字,因为msg 是不可变类型,所以msg由原来的outisde变成inside,值变了,python就会重新开辟新内存,导致不能修改“原来的值outside”

def outside():
    msg = "Outside!"
    def inside():
        nonlocal msg  # 若去掉, 则修改不会成功。结果输出“outside!”
        msg = "Inside!"
    inside()
    print(msg)
outside()
Inside!

但是该变量不能作用于全局变量。因为也好理解,如果你要修改,则可以用global
如下,会报错:

msg = "Outside!"

def outside():
    def inside():
        nonlocal msg
        msg = "Inside!"
    inside()
    print(msg)
outside()
 nonlocal msg
    ^
SyntaxError: no binding for nonlocal 'msg' found

补充例子:
如下,对于可变类型,在外层函数id(d)和内层函数id(d)是一致的,而修改的是d["outside"]会导致内存改变——d['outside']是不可变类型,如下使用id(d['outside'])查看确实改变了,但是对于整体的id(d)是不变的,所以不需要使用nonlocal也可以修改成功

def outside():
    d = {"outside": 'init'}
    print(id(d))
    print(id(d['outside']))
    def inside():
        d["outside"] = 'change'
        print(id(d))  # 是一致的, 没有改变
        print(id(d['outside']))  # 改变了,但是只要id(d)未改变就能修改成功
    inside()
    print(d)
outside()
{'outside': 'change'}
posted @ 2020-09-19 14:24  孔胡子  阅读(276)  评论(0编辑  收藏  举报