搜索
首页后端开发Python教程python闭包中变量引用分析

python闭包中变量引用分析

Dec 08, 2016 am 10:57 AM
python

标题看起来很虎人,其实不敢称为分析。自己这方面仍有欠缺,以前也许还行,现在专门研究语言的时间和精力没那么多了。有解释的不对的地方欢迎各位来板砖,别误导了大众。

还是直接说这次的问题,今天@neiddy(javaeye)跟我说起闭包的问题,看那几个例子好有意思,想搞懂的冲动。

看两段代码:

>>> def foo():
       a = 1
       def bar():
              a = a +1
              return a
       return bar()
 
>>> foo()
Traceback (most recent call last):
  File "<pyshell#73>", line 1, in <module>
    foo()
  File "<pyshell#72>", line 6, in foo
    return bar()
  File "<pyshell#72>", line 4, in bar
    a = a +1
UnboundLocalError: local variable &#39;a&#39; referenced before assignment
>>> def foo():
       a = [1]
       def bar():
              a[0] = a[0] + 1
              return a[0]
       return bar()
 
>>> foo()2

通过闭包体验函数式编程,还是不错的感觉。原文下面少了括号,不然返回函数本身就没意思了。再说这个神奇的现象,文中只是说改成容器就ok了,为什么呢?

Google了一些内存管理内存分配的东西,都没有找到出路,走投无路只能投奔源码了。从没看过直接看效率太低,幸好有人总结过了,推荐一下”雨痕 Q.yuhen”的《深入Python编程》,实属低调的大神。

直接闭包部分的代码分析雨痕在闭包的一节有讲到,但是没有专门说这个奇怪的问题的机制。

重复的看书吧,参照了书中的’参数’和’闭包’两节,下面说说根据他的讲解和附上的源码,谈谈我的理解。

雨痕在章节的最后提到”CPython实现闭包的原理并不复杂,说白了就是将所引用的外层对象附加到每次都重新创建的内层函数对象身上 (func_closure)。”

这句话是对前面的概括,同时也包含了重要的信息,就是内部函数对应的对象访问外层函数中的变量其实是通过将外层的变量引用到内存对象的堆栈中来访问的,C语言的代码中时按值传递的。

比如第一段代码中的a,其实是引用了1过来,本身的co_nlocals是1,即一个局部变量是等号前面的a(这样说不太对,只是希望帮助理解这个问题)。既然是局部变量a,a = a +1必然是要抛出UnboundLocalError的。

而对于第二个问题,虽然存在一样的情况,但是即便按值传递,数组中每个位置的指针指向的具体是不变的,还是会修改指定位置的值,因此如果是容器型对象就是可行的。

 

痛恨自己的就是这个地方总感觉自己说不清楚,其实就是刚学c语言的时候常玩的指针类游戏,虽然说的很烂,但希望指到要害了。接下来就很简单了,按照这个思路来验证一段代码,也就是如果只是输出这个值,不设定局部变量的话那么应该是可以运行的。

>>> def foo():
       a = 1
       def bar():
              return a
       return bar()
 
>>> foo()
1

事情果然跟预想的一样发生了。再细细的体会,好好看看雨痕带着分析的代码吧。了解机制走的更远。Python越来越有意思了,用python的思想写代码,益处良多啊。

By the way,顺带

>>> flist = []
>>> for i in range(3):
       def foo(x): print x + i
       flist.append(foo)
 
>>> for f in flist:
       f(2)
 
4
4
4

文中提到这段代码是因为i不被销毁导致的,今天搜内存分配的时候也看到这个东西。编程的时候应该尽量使用list comprehension减少for和while,一是函数化编程简洁明了,另一方面是性能提升和节省一个计数器。

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Python vs.C:申请和用例Python vs.C:申请和用例Apr 12, 2025 am 12:01 AM

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。 Python以简洁和强大的生态系统着称,C 则以高性能和底层控制能力闻名。

2小时的Python计划:一种现实的方法2小时的Python计划:一种现实的方法Apr 11, 2025 am 12:04 AM

2小时内可以学会Python的基本编程概念和技能。1.学习变量和数据类型,2.掌握控制流(条件语句和循环),3.理解函数的定义和使用,4.通过简单示例和代码片段快速上手Python编程。

Python:探索其主要应用程序Python:探索其主要应用程序Apr 10, 2025 am 09:41 AM

Python在web开发、数据科学、机器学习、自动化和脚本编写等领域有广泛应用。1)在web开发中,Django和Flask框架简化了开发过程。2)数据科学和机器学习领域,NumPy、Pandas、Scikit-learn和TensorFlow库提供了强大支持。3)自动化和脚本编写方面,Python适用于自动化测试和系统管理等任务。

您可以在2小时内学到多少python?您可以在2小时内学到多少python?Apr 09, 2025 pm 04:33 PM

两小时内可以学到Python的基础知识。1.学习变量和数据类型,2.掌握控制结构如if语句和循环,3.了解函数的定义和使用。这些将帮助你开始编写简单的Python程序。

如何在10小时内通过项目和问题驱动的方式教计算机小白编程基础?如何在10小时内通过项目和问题驱动的方式教计算机小白编程基础?Apr 02, 2025 am 07:18 AM

如何在10小时内教计算机小白编程基础?如果你只有10个小时来教计算机小白一些编程知识,你会选择教些什么�...

如何在使用 Fiddler Everywhere 进行中间人读取时避免被浏览器检测到?如何在使用 Fiddler Everywhere 进行中间人读取时避免被浏览器检测到?Apr 02, 2025 am 07:15 AM

使用FiddlerEverywhere进行中间人读取时如何避免被检测到当你使用FiddlerEverywhere...

Python 3.6加载Pickle文件报错"__builtin__"模块未找到怎么办?Python 3.6加载Pickle文件报错"__builtin__"模块未找到怎么办?Apr 02, 2025 am 07:12 AM

Python3.6环境下加载Pickle文件报错:ModuleNotFoundError:Nomodulenamed...

如何提高jieba分词在景区评论分析中的准确性?如何提高jieba分词在景区评论分析中的准确性?Apr 02, 2025 am 07:09 AM

如何解决jieba分词在景区评论分析中的问题?当我们在进行景区评论分析时,往往会使用jieba分词工具来处理文�...

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器