Python 闭包坑点

640

闭包坑点

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

 
  
  1. In [6]: def boy(pos):

  2. ...: def run(step):

  3. ...: pos = pos + step

  4. ...: return pos

  5. ...: return run

  6. ...:


  7. In [7]: r = boy(0)


  8. In [9]: r(10)

  9. ---------------------------------------------------------------------------

  10. UnboundLocalError Traceback (most recent call last)

  11. <ipython-input-9-5a4ba556b403> in <module>

  12. ----> 1 r(10)


  13. <ipython-input-6-9b6d05d20cb3> in run(step)

  14. 1 def boy(pos):

  15. 2 def run(step):

  16. ----> 3 pos = pos + step

  17. 4 return pos

  18. 5 return run


  19. UnboundLocalError: local variable 'pos' referenced before assignment



640

分析原因

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


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



640

解决措施

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

 
  
  1. In [14]: def boy(pos):

  2. ...: def run(step):

  3. ...: nonlocal pos

  4. ...: pos = pos + step

  5. ...: return pos

  6. ...: return run


  7. In [15]: r = boy(0)


  8. In [16]: r(10)

  9. Out[16]: 10


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

演示代码如下:


 
  
  1. In [14]: def boy(pos):

  2. ...: def run(step):

  3. ...: nonlocal pos

  4. ...: pos = pos + step

  5. ...: return pos

  6. ...: return run


  7. In [15]: run = boy(0)


  8. In [16]: run(10)

  9. Out[16]: 10


  10. In [17]: run(20)

  11. Out[17]: 30


  12. In [18]: run(10)

  13. Out[18]: 40

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




更多文章,点击图片


640?wx_fmt=png


640?wx_fmt=png


640?wx_fmt=jpeg

长按订阅


smiley_66.png点个好看

猜你喜欢

转载自blog.csdn.net/xo3ylAF9kGs/article/details/89702328