为什么要使用nonlocal

  Python3中加入了新的关键字nonlocal,当在一个嵌套的函数中对变量申明为nonlocal时,就明确表示这个变量是外部函数中定义的变量。也许会有这么一个问题:按照python的LEGB原则,在函数本地作用域找不到变量的情况下,解释器会自动在外层函数寻找,nonlocal关键字岂不是显得多余?   是的,当一个函数在本地作用域找不到变量申明时会向外层函数寻找,这在函数闭包中很常见。如下:

1 def test(num1):
2     def add(num2):
3         return num1 + num2
4     return add
5
6 a = test(1)
7 b = test(2)
8 print(a(1))
9 print(b(1))

输出为:

2
3

但是在本地作用域中使用的变量后,还想对此变量进行更改赋值就会报错。如下:

def test():
    count = 1
    def add():
        print(count)
        count += 1
    return add

a = test()
a()

输出为:

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-6-24732f13d2b6> in <module>()
      7
      8 a = test()
----> 9 a()

<ipython-input-6-24732f13d2b6> in add()
      2     count = 1
      3     def add():
----> 4         print(count)
      5         count += 1
      6     return add

UnboundLocalError: local variable ‘count‘ referenced before assignment

在上面代码中,如果在使用count前面加上关键字nonlocal申明就可解决这个问题:

def add():
    count = 1
    def fun():
        nonlocal count
        print(count)
        count += 1
    return fun

a = add()
a()
a()

输出为:

1
2

  上面代码完美地解决了函数嵌套调用外部变量的问题;另外,如果从另一个角度来看我们给此函数增加了记录函数状态的功能。当然,这也可以通过申明全局变量来实现增加函数状态的功能。当这样会出现以下问题:

  1. 每次调用函数时,都得在全局作用域申明变量。别人调用函数时还得查看函数内部代码。

  2. 当函数在多个地方被调用并且同时记录着很多状态时,会造成非常地混乱。

  使用nonlocal的好处是,在为函数添加状态时不用额外地添加全局变量,因此可以大量地调用此函数并同时记录着多个函数状态,每个函数都是独立、独特的。针对此项功能其实还个一个方法,就是使用类,通过定义__call__可实现在一个实例上直接像函数一样调用。

时间: 2024-08-05 16:49:11

为什么要使用nonlocal的相关文章

global与nonlocal

global与nonlocal:   global关键字:   x=1 def foo(): x=10 print(x)     #打印: 10 foo() print(x)          #打印:  1 #############>>>局部的x不会影响全局的x x=1 def foo():                        #使用global关键字,在局部修改全局变量 global x x=10 print(x)     #打印: 10 foo() print(x)  

python中global 和 nonlocal 的作用域

python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量 . 一 global global关键字用来在函数或其他局部作用域中使用全局变量.但是如果不修改全局变量也可以不使用global关键字. 1 gcount = 0 2 3 def global_test(): 4 gcount+=1 5 print (gcount) 6 global_test() D:\Python34\python.exe E:/PycharmProje

3.关于作用域知识的额外补充global和nonlocal关键字

本遍文章对global关键字和nonlocal关键字进行补充,这两个关键字在以后做python开发的时候,能不用尽量别用!最好别用!总会出现让你意想不到的后果... 1.先说第一种global,不管在任何作用域下,只要是使用global声明的变量,都会变为全局变量. 直接上例子. 首先是不使用global声明变量. x = 1 def f1(): x = "suhaozhi" print x def f2(): x = "hamasakiayumi" print x

nonlocal(非局部变量)---python&#160;3.x 新增关健词

Python里只有2种作用域:全局作用域和局部作用域.全局作用域是指当前代码所在模块的作用域,局部作用域是指当前函数或方法所在的作用域.其实准确来说,Python 3.x引入了nonlocal关键字,可以用于标识外部作用域的变量. 局部作用域里的代码可以读取外部作用域(包括全局作用域)里的变量,但不能更改它.一旦进行更改,就会将其当成是局部变量.而如果在更改前又进行了读取操作,则会抛出异常. 为了解决这个问题,Python 3.x引入了nonlocal关键字(详见The nonlocal sta

基于MST的立体匹配及相关改进(A Non-Local Cost Aggregation Method for Stereo Matching)

怀着很纠结的心情来总结这篇论文,这主要是因为作者提虽然供了源代码,但是我并没有仔细去深究他的code,只是把他的算法加进了自己的项目.希望以后有时间能把MST这一结构自己编程实现!! 论文题目是基于非局部代价聚类(non-local cost aggregation)的立体匹配,从题目上看这篇论文不是局部算法,但是也不是传统意义上的全局算法.这要从基于窗结构局部立体匹配算法说起,如下图: 我们求左右两幅图像在视差d下一点的cost时,我们实际是求得以该点为中心半径为r的Windows内所有点的c

Passing address of non-local object to __autoreleasing parameter for write-back

在希望通过函数的参数返回Objective-C对象的时候,遇到了这个问题 错误代码如下: - (void)methodA:(NSString **)string<span style="white-space:pre"> </span>// 其实,这里的参数实际类型是:(NSString * __autoreleasing * )string { *string = XXX; } 正确的用法是 - (void)methodA:(NSString * __stro

Python 关键字之 nonlocal

在Python 3.x中增加了nonlocal关键字,关于变量的声明,引自官方文档: Assignment of an object to a single target is recursively defined as follows. If the target is an identifier (name): If the name does not occur in a global or nonlocal statement in the current code block: th

python global vs nonlocal (2)

上一篇中简述了这两个关键字的基本用法: global用于在局部作用于修改或重定义全局变量 nonlocal用于在内部作用域修改或重定义外部变量(全局变量除外) 这只是很浅的理解方式 注意python的特性,变量有mutable和immutable之分,对于mutable变量的,在内部作用域内做修改时完全可以的,不需要上面两个关键字的修饰,比如下面的程序: a = 12li = [1, 2, 3]def g():    b = 11    li[2] = 4   #li变量在内部作用域内被修改了 

python3 nonlocal vs global

考虑这样一个python程序: x = 12 def func(): x = 1 func() print(x) 输出为:x = 12 因为函数内部定义的x被认为只属于局部作用域,为了表明我么引用的是全局的x而不是新定义一个局部的x, 可以使用global关键字: x = 12 def func(); global x x = 1 func() print(x) 可以发现输出已经变成了1,也就是在函数内部成功修改了一个全局变量 还有一种情形,就是嵌套的局部作用域的问题: def g(): x =