前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python 闭包坑点

Python 闭包坑点

作者头像
double
发布2019-05-13 15:48:29
6640
发布2019-05-13 15:48:29
举报
文章被收录于专栏:算法channel

闭包坑点

上篇参考:Python 闭包使用注意点,接下来,介绍使用闭包,经常会犯的一个错误:演示代码如下,

代码语言:javascript
复制
In [6]: def boy(pos):    ...:     def run(step):    ...:         pos = pos + step    ...:         return pos    ...:     return run    ...:                                                                         
In [7]: r = boy(0) 
In [9]: r(10)                                                                   ---------------------------------------------------------------------------UnboundLocalError                         Traceback (most recent call last)<ipython-input-9-5a4ba556b403> in <module>----> 1 r(10)
<ipython-input-6-9b6d05d20cb3> in run(step)      1 def boy(pos):      2     def run(step):----> 3         pos = pos + step      4         return pos      5     return run
UnboundLocalError: local variable 'pos' referenced before assignment

分析原因

python 规则指定所有在赋值语句左面的变量都是局部变量,则在闭包 run() 中,变量 pos 在赋值符号"="的左面,被 python 认为是 run() 中的局部变量。

再接下来执行 r() 时,程序运行至 pos = pos + step 时,因为先前已经把 pos 归为 run() 中的局部变量,所以 python 会在 run() 中去找在赋值语句右面的 pos 的值,结果找不到,就会报错。

解决措施

在 python3 以后,在 pos = pos + 1 之前,使用语句 nonloacal pos 显式的指定 pos 不是闭包的局部变量。

代码语言:javascript
复制
In [14]: def boy(pos):     ...:     def run(step):     ...:         nonlocal pos     ...:         pos = pos + step     ...:         return pos     ...:     return run                                                                      
In [15]: r = boy(0)                                                             
In [16]: r(10)                                                                  Out[16]: 10

我们可以利用,闭包执行完后仍然能够保持住当前的运行环境。

演示代码如下:

代码语言:javascript
复制
In [14]: def boy(pos):     ...:     def run(step):     ...:         nonlocal pos     ...:         pos = pos + step     ...:         return pos     ...:     return run                                                                         
In [15]: run = boy(0)                                                             
In [16]: run(10)                                                                  Out[16]: 10
In [17]: run(20)                                                                  Out[17]: 30
In [18]: run(10)                                                                  Out[18]: 40

可以看出,返回的闭包 run 中保存了 pos的值,下次执行闭包会记住上次 pos 的值,这就是闭包的数据持久化功能。文章参考:https://www.cnblogs.com/JohnABC/p/4076855.html


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员郭震zhenguo 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档