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

 def test(num1):
def add(num2):
return num1 + num2
return add a = test(1)
b = test(2)
print(a(1))
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__可实现在一个实例上直接像函数一样调用。

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

  1. python中global 和 nonlocal 的作用域

    python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量 . 一 global global关键字用来在函数或其他局部作用域 ...

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

    怀着很纠结的心情来总结这篇论文,这主要是因为作者提虽然供了源代码,但是我并没有仔细去深究他的code,只是把他的算法加进了自己的项目.希望以后有时间能把MST这一结构自己编程实现!! 论文题目是基于非 ...

  3. python global vs nonlocal (2)

    上一篇中简述了这两个关键字的基本用法: global用于在局部作用于修改或重定义全局变量 nonlocal用于在内部作用域修改或重定义外部变量(全局变量除外) 这只是很浅的理解方式 注意python的 ...

  4. python3 nonlocal vs global

    考虑这样一个python程序: x = 12 def func(): x = 1 func() print(x) 输出为:x = 12 因为函数内部定义的x被认为只属于局部作用域,为了表明我么引用的是 ...

  5. global & nonlocal

    name = "A" def test(): name = "B" def test2(): global name # global 指的是拿到的是全局的变量 ...

  6. python新增nonlocal关键字

    def fa(a): b = 2 def fb(): nonlocal b print(b) return fbc = 2fa(22)()# python作用域:LEGB

  7. python 闭包计算移动均值及nonlocal的使用

    class Averager1(): '''计算移动平均值的类第一种写法''' def __init__(self): self.series = [] def __call__(self,new_v ...

  8. global与nonlocal关键字总结

    global适用于函数内部修改全局变量的值 nonlocal适用于嵌套函数中内部函数修改外部变量的值 如果没有使用以上关键字,对全局变量或者外部变量进行修改,python会默认将全局变量隐藏起来 例1 ...

  9. 全局变量&局部变量,global&nonlocal

    ###全局变量与局部变量 1.函数内部的变量名如果第一次出现,且出现在=前面,即被视为定义一个局部变量,不管全局域中有没有用到该变量名,函数中使用的将是局部变量 2.函数内部的变量名如果第一次出现,且 ...

  10. python3的变量作用域规则和nonlocal关键字

    也许你已经觉得自己可以熟练使用python并能胜任许多开发任务,所以这篇文章是在浪费你的时间.不过别着急,我们先从一个例子开始: i = 0 def f(): print(i) i += 1 prin ...

随机推荐

  1. android-退出动画无效

    在调用 overridePendingTransition(R.anim.anim_scale_in, R.anim.anim_scale_out); 方法设置某个Activity进入和退出动画的时候 ...

  2. jquery的input:type=file实现文件上传

    <!DOCTYPE html> <html> <head> <title>html5_2.html</title> <style> ...

  3. 公共查询类criteria

    package cn.edu.hbcf.common.vo; import java.math.BigDecimal; import java.sql.Timestamp; import java.u ...

  4. QBC运算符含义

    HQL运算符                   QBC运算符                      含义      =                     Restrictions.eq() ...

  5. redis数据类型List的安全队列和不安全队列

    在学习RPOPLPUSH命令的时候,官方文档中有提到安全队列和不安全的队列,一开始没有看懂,现在理解了做个笔记. 一般情况下,我们可以借助List来实现消息队列,比如一个客户端通过命令LPUSH(BL ...

  6. 架构探险——第三章(搭建轻量级Java Web框架)

    解决的问题 servlet的数量会随业务功能的扩展而不断增加,我们有必要减少servlet的数量,交给controller处理,它负责调用service的相关方法,并将返回值放入request或res ...

  7. hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙

    /** 题目:hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4106 ...

  8. Python中sort以及sorted函数初探

    sorted(...) Help on built-in function sorted in module __builtin__: sorted(...) sorted(iterable, cmp ...

  9. 在CentOS 7上利用systemctl添加自定义系统服务 /usr/lib/systemd/

    在CentOS 7上利用systemctl添加自定义系统服务[日期:2014-07-21] 来源:blog.csdn.net/yuanguozhengjust 作者:yuanguozhengjust ...

  10. idea传入HttpServletRequest时显示cannot resolve symbol的问题

    在使用idea ide的时候,在控制器中我需要获取HttpServletRequest这个request对象,编译时出现cannot resolve symbol的问题,然后网上查找资料,这里记录一下 ...