标题看起来很虎人,其实不敢称为分析。自己这方面仍有欠缺,以前也许还行,现在专门研究语言的时间和精力没那么多了。有解释的不对的地方欢迎各位来板砖,别误导了大众。
还是直接说这次的问题,今天@neiddy(javaeye)跟我说起闭包的问题,看那几个例子好有意思,想搞懂的冲动。关于python闭包的问题如果不了解的话,这篇文章还是很不错的:
http://blog.csdn.net/marty_fu/article/details/7679297
问题也源于文中提到的例子。
看两段代码:
>>> 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 'a' 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,一是函数化编程简洁明了,另一方面是性能提升和节省一个计数器。
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com