python中的nonlocal与global的用法

python中引用变量的顺序为当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量

而python中unlocal的作用为变当前作用域局部变量最临近外层(非全局)作用域变量

而global的作用为变当前作用域局部变量当前模块中的全局变量


1.unlocal

先来看下面一个简单的例子:

def test_nonlocal():
    dd = 0
    def test2():
        dd += 2
    test2()
    print(dd)
test_nonlocal()
Traceback (most recent call last):
  File "D:/python/leetcode/test1.py", line 7, in <module>
    test_unlocal()
  File "D:/python/leetcode/test1.py", line 5, in test_unlocal
    test2()
  File "D:/python/leetcode/test1.py", line 4, in test2
    dd += 1
UnboundLocalError: local variable 'dd' referenced before assignment

在这里会出现错误,可以看到,dd在这里没有定义,这是因为dd是在test_unlocal中定义的。当在内部函数引用外部函数的变量时,它会认为这是一个内部函数的局部变量,但是在内部函数test2中,因为没有调用dd的值,所以会报错。

这里unlocal的作用就会显现出来了:

def test_nonlocal():
    dd = 0
    def test2():
        nonlocal dd
        dd += 2
    test2()
    print(dd)
test_nonlocal()
>>>2

加上nonlocal,就是说明将dd的作用域提到上面临近一层,也就是test_nonlocal那一层

但是在内部函数直接引用倒是没有问题,也就是说不作任何修改,直接用。

def test_nonlocal():
    dd = 0
    def test2():
         print(dd)
    test2()
test_nonlocal()
>>>0

这样就不会报错。

def test_nonlocal():
    dd = 0
    def test2():
        def test3():
            nonlocal dd
            dd += 2
        test3()
    test2()
    print(dd)
test_nonlocal()
>>>2
当调用的作用域在内部几层时,在上个例子中,最临近外层为test_nonlocal,故输出为2


def test_nonlocal():
    dd = 0
    def test2():
        def test3():
            dd = 3
            def test4():
                nonlocal dd
                dd += 2
                print(dd)
            test4()
        test3()
    test2()
    print(dd)
test_nonlocal()
>>>5

>>>0

但在上面的例子中,最邻近外层为test3,故先输出5,再输出0

但当最邻近外面为全局变量时,便会报错:

dd = 0
def test_nonlocal():
    nonlocal dd
    dd += 2
    print(dd)
test_nonlocal()

File "D:/python/leetcode/test3.py", line 3

  nonlocal dd
SyntaxError: no binding for nonlocal 'dd' found

所以nonlocal只能引用到最外层非全局变量。


2.global

对于global语句来说,性质与nonlocal差不多,只不过global是将变量直接变为全局变量。

dd = 0
def test_global():
    def test2():
         dd += 2
    test2()
test_global()

Traceback (most recent call last):

  File "D:/python/leetcode/test1.py", line 7, in <module>
    test_nonlocal()
  File "D:/python/leetcode/test1.py", line 6, in test_nonlocal
    test2()
  File "D:/python/leetcode/test1.py", line 5, in test2
    dd += 2
UnboundLocalError: local variable 'dd' referenced before assignment

上述代码同样报错


dd = 0
def test_global():
    def test2():
        global dd
        dd += 2
        print(dd)
    test2()
test_global()
>>>0

同样的,也是可以引用的。

dd = 0
def test_global():
    def test2():
        global dd
        dd += 2
    dd += 2
    test2()
test_global()

Traceback (most recent call last):
  File "D:/python/leetcode/test1.py", line 9, in <module>
    test_nonlocal()
  File "D:/python/leetcode/test1.py", line 7, in test_nonlocal
    dd += 2
UnboundLocalError: local variable 'dd' referenced before assignment

但是,在test2中定义的dd为global,运用作用域也仅限于在test2中,在外层应用时,同样也会出错。


dd = 0
def test_global():
    def test2():
        global dd
        dd += 2
    global dd
    test2()
    dd += 2
    print(dd)

test_global()

>>>4

在外层使用时,同样需要使用global


3.总结

当在不同的作用域调用变量是,一定要注意变量的作用域范围。

unlocal的作用为变当前作用域局部变量最临近外层(非全局)作用域变量

而global的作用为变当前作用域局部变量当前模块中的全局变量

当试图去修改,不同作用域中的变量的值时,python会自动创建一个在那个作用域里面的同名变量,变量的作用范围仅限于此作用域。

但是仅仅是引用变量确是可以引用的。

下面再看一个简单的例子:

def test():
    def local_test():
        spam = "local spam"
    def nonlocal_test():
        nonlocal  spam
        spam = "nonlocal spam"
    def global_test():
        global spam
        spam = "global spam"
    spam = "test spam"
    local_test()
    print("After local assignmane:", spam)
    nonlocal_test()
    print("After nonlocal assignment:",spam)
    global_test()
    print("After global assignment:",spam)

After local assignmane: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam

这说明在global_test中,创建的是全局变量。

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值