标题看起来很虎人,其实不敢称为分析。自己这方面仍有欠缺,以前也许还行,现在专门研究语言的时间和精力没那么多了。有解释的不对的地方欢迎各位来板砖,别误导了大众。
还是直接说这次的问题,今天@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,一是函数化编程简洁明了,另一方面是性能提升和节省一个计数器。
相关推荐
8. **垃圾回收与闭包**:Python的垃圾回收机制会考虑闭包的存在,只要闭包还被引用,它所访问的外部变量就不会被回收。 通过以上的知识点,你可以开始尝试解决“python高阶闭包练习题”中的问题。在实践中应用这些...
总的来说,闭包在Python中是一个非常有趣且复杂的话题,它涉及到变量的作用域、引用机制、对象的生命周期管理以及函数的动态执行等多个方面。理解闭包及其引用环境有助于编写更加高效且健壮的Python代码。在实际编程...
本文实例讲述了Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作。分享给大家供大家参考,具体如下: 实例对象也可以实现闭包的功能,不过实例对象消耗的资源(内存)比闭包多。 demo.py(闭包): # 闭包,...
闭包(Closure)是 Python 中一个特殊的概念,它是指在函数内部定义的函数,可以访问外部作用域中的变量,这样可以将变量与函数捆绑在一起,形成一个闭包。闭包是 Python 实现最内嵌套作用域规则的方案。 变量的...
Python闭包是编程语言中的一种高级特性,它在函数式编程和面向对象编程中都扮演着重要的角色。在Python中,闭包是指一个内嵌函数(nested function)对其外部作用域变量的引用,即使外部函数已经执行完毕,闭包依然...
闭包函数的定义:在Python中,闭包是由一个外部函数和一个内部函数组成的,内部函数引用了外部函数的局部变量,即使外部函数已经执行完毕,这些变量仍然可以被内部函数访问。这通常是因为内部函数在被创建时就绑定了...
Python中的闭包是一种重要的编程概念,它涉及到代码块、局部变量、全局变量和自由变量等基本概念。在Python中,代码块包括模块、函数体和类定义等。局部变量是在特定代码块中定义并绑定的变量,全局变量则在模块级别...
闭包是函数式编程中的一个重要概念,在Python中通过嵌套函数实现闭包。闭包的主要作用是使一个内层函数能够记住并访问外层函数的作用域,即使外层函数执行完毕后,内层函数仍然可以使用外层函数的局部变量。 在...
Python中的闭包是一种重要的编程概念,它涉及到函数、作用域和引用等核心概念。闭包在Python编程中扮演着至关重要的角色,特别是在处理高阶函数、数据封装和异步编程等场景。以下是对闭包的详细解释: 1. **闭包的...
Python 中的变量名引用遵循 LEGB 法则,即 Local、Enclosing、Global 和 Built-in。Python 在查找变量时,首先在局部作用域中查找,然后是外部作用域、全局作用域和内置作用域。 闭包(Closure)是 Python 中的一种...
Python闭包可能会在面试或者是工作中经常碰到,而提到Python的延迟绑定,肯定就离不开闭包的理解,今天总结下 关于闭包的概念以及一个延迟绑定的面试题。 Python闭包 1、什么是闭包,闭包必须满足以下3个条件: 必须...
### Python闭包开发知识点 #### 一、理解Python闭包 在Python中,闭包(Closure)是一种特殊类型...通过上述分析和解决方案,我们可以更好地理解和利用Python闭包的功能,避免常见的陷阱,提高代码的质量和可维护性。
本篇文章将深入探讨如何利用Python闭包来实现一个简单的计数器,并解释闭包的基本概念和相关技巧。 首先,我们要理解闭包的核心特征:一个函数内部定义了另一个函数,并且内部函数引用了外部函数的局部变量。当外部...
Python还有一种闭包变量,存在于函数内部但超出局部作用域。变量的生命周期由其最后一次赋值决定,直到程序结束或者对象被垃圾回收。 6. 异常处理与类型检查: Python在赋值过程中会自动进行类型转换,但如果尝试将...
关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被称为闭包...
什么是闭包?如何设置闭包?创建闭包可以用来干什么?闭包的好处,如何正确使用闭包?通过闭包能创建一些只有当前函数能访问的变量,
在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由...
在Python中,闭包通常由嵌套函数和对外部变量的引用组成。 一、函数作为返回值 在Python中,函数是可以当作值来使用的,这意味着我们可以将函数作为参数传递给其他函数,也可以从一个函数中返回另一个函数。下面是...