python闭包closure
在讨论闭包之前,先总结一下python的命名空间namespace,一般的语言都是通过namespace来识别名字标识,无论是变量,对象,函数等等。python划分3个名字空间层次,local:局部,标识为当前函数内,当前类内,比如局部变量。global:全局,标识当前模块,也就是当前文件,比如全局变量等。最后一类 built-in,内建,这个是作用域比较大,跨模块(文件)都可以标识,比如我们自建的文件中,引用内建函数dir(), 这就是一个典型的例子,自建的文件中能够并没有声明dir(),但由于dir()是built_in内建函数,故在所有文件或模块都可以引用。
再来讨论闭包:百度上对闭包的定义是:闭包是指可以包含自由变量的代码块。定义简单明了,也有把自由变量成为环境变量的。紧接着定义什么是自由变量或环境变量:这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。结合namespace的概念,自由变量的位置:既不在函数local范围内,也不在全局global范围内,而是在两个函数的作用域之间。举个例子:
def numFunc(a, b):
num = 100
num2 = 200
num3 = 300
print('print s in numbunc', s) def addfunc(a, b):
s = 'string in addfunc'
x = num
y = num3
print('print s in addFunc', s) return addfunc
num, num2, num3, 这三个变量符合自由变量的描述,既不在局部local内,也不再全局global内。而是在两个函数的作用域之间。
所以咱们说白了,闭包从形式上说,就是函数内嵌一个函数。但是还需满足两个条件,1.内层函数引用环境变量(自由变量)2外部函数返值为内部函数名(一个返回函数的高阶函数)
再来说闭包有什么用? 闭包减少了参数的传递数量, 设计闭包是为了增加代码重复利用。还有的文章中说到,闭包是为了方便并行计算设计的,随着我们深入学习,会继续充实这篇文章,发觉闭包的更多作用。另外是不是跟装饰器有点像呢?其实本质上,decorator就是一个返回函数的高阶函数,闭包也是一个返回函数的高阶函数。从这个角度上说 装饰器也是闭包,闭包也是装饰器。区别在于装饰器希望在代码运行期间动态增加功能,闭包希望简化参数的调用提高代码利用率
闭包的特性 __closure__
__closure__是内部函数的一个属性,用来保存环境变量,用type()函数看一下,__closure__是一个tulple, 还以上边的代码为例,我们看一下环境变量都包含什么,什么样的变量可以记录到环境变量中得以保存:

从结果中我们看到,num和num3被保存了下来,而num2没有被保存,原因很简单,因为定义中,内部函数必须引用自由变量,num2没有被引用。
再来看一个例子,帮助我们理解,解释器是如何保存环境变量到__closure__中来的,我把廖雪峰的例子做了修改:
def count():
fs = []
for i in range(1, 4):
def f():
return i*i return f f = count()
x = None
x = f() pass
我们单步跟进,发现,在每次循环中,f()只是声明,没有执行,所以每次循环,return i*i并没有被执行。循环结束i = 3,在这时,count()函数返回,解释器将环境变量 i 保存到__closure__中去,i = 3,打扫好现场,count()的堆栈,上下文撤销
所有环境变量都是在函数闭包声明结束是完成初始化。下面我们用一个例子来说明:
第一步: 定义闭包之前,__closure__这个属性没有值

第二步:最关键的一步: 我们发现,在闭包声明结束的时候,内部函数的还将变量就已经确定下来了,不需要等到执行内部函数才确定环境变量。

闭包的不习惯
在c/c++中好像没有闭包的概念,也没有环境变量(自由变量)的概念,所以函数包含函数,或者外部函数返回内部函数,会造成异常,因为内部函数返回,堆栈消失,所有内部变量都不存在了。而python的闭包设计是允许返回局部变量的,这给我们这些从c/c++转过来的少年带来了很大的不适应,总感觉要出大事,这时候想想__closure__属性,python的闭包设计使推出内部函数后,没有回收内部函数的部分资源,而是作为环境变量保存下来了,慢慢习惯。
python闭包closure的更多相关文章
- python 闭包(closure)
闭包的定义: 闭包就是一个函数,这个函数可以记住封闭作用域里的值,而不管封闭作用域是否还在内存中. 来一个例子: def happy_add(a): print 'id(a): %x' % id(a) ...
- Python闭包Closure 2
由于Python中,变量作用域为LEGB,所以在函数内部可以读取外部变量,但是在函数外不能读取函数内的变量.但是出于种种原因,我们需要读取函数内的变量时候怎么办?那就是在函数内在加一个函数. def ...
- python 闭包 Closure 函数作为返回值
一.函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. >>> def lazy_sum(*args): ... def sum(): ... ax = ...
- python 函数对象(函数式编程 lambda、map、filter、reduce)、闭包(closure)
1.函数对象 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 秉承着一切皆对象的理念,我们再次回头来看函数(function).函 ...
- Python 闭包(Closure)
Python 闭包 (Closure) 这里介绍一下python 的闭包 基本概念 闭包(closure)是函数式编程的重要的语法结构. 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函 ...
- 【Python】闭包Closure
原来这就是闭包啊... 还是上次面试,被问只不知掉js里面的闭包 闭包,没听过啊...什么是闭包 回来查了下,原来这货叫闭包啊...... —————————————————————————————— ...
- Python 闭包
什么是闭包? 闭包(closure)是词法闭包(lexical closure)的简称.闭包不是新奇的概念,而是早在高级程序语言开始发展的年代就已产生. 对闭包的理解大致分为两类,将闭包视为函数或者是 ...
- Python闭包与javascript闭包比较
实例一 python def line_conf(): def line(x): return 2*x+1 print(line(5)) # within the scope line_con ...
- Python闭包与函数对象
1. Python闭包是什么 在python中有函数闭包的概念,这个概念是什么意思呢,查看Wikipedia的说明如下: “ In programming languages, closures (a ...
随机推荐
- 高性能mysql第6章
第6章,优化配置 https://www.cnblogs.com/musings/p/5913157.html 1:服务器读取的配置文件,可以使用下面的命令查询 admin@iZwz92c0zpe8t ...
- 深度学习Momentum(动量方法)
转自:http://blog.csdn.net/bvl10101111/article/details/72615621 先上结论: 1.动量方法主要是为了解决Hessian矩阵病态条件问题(直观上讲 ...
- win10 + cuda(v9.0) 安装TensorFlow-gpu版
之前在实习公司的电脑上装过TensorFlow-gpu,那时候很快就装好了.但在自己的笔记本上装时,却搞了很久... 一部分原因是因为用校园网下载cuda toolkit 和cudnn ,总是在最后时 ...
- Selenium Webdriver——操作隐藏的元素(二)display属性
有时候我们会碰到一些元素不可见,这个时候selenium就无法对这些元素进行操作了.例如,下面的情况: 页面主要通过“display:none”来控制整个下拉框不可见.这个时候如果直接操作这个下拉框, ...
- Python os.path.dirname(__file__) 与 Python os.path.abspath(__file__) 与 os.system() 函数
Python os.path.dirname(__file__) 与 Python os.path.abspath(__file__) 的区别 os.path.abspath(__file__)返回 ...
- Oracle存储过程中游标的简单使用
存储过程中查询语句如何返回多行结果? 我们知道,如果存储过程中查询语句有多行结果输出,会报错:ORA-01422: exact fetch returns more than requested nu ...
- 7zip
1.下载地址. https://www.7-zip.org/ 2.傻瓜式安装.
- mysql的锁机制
一.读锁(共享锁/Share Locks,S锁). 1.select * from table_name where ... lock in share mode.(事务A) (1)这种方式是获取指定 ...
- VS2010/MFC编程入门之三十三(常用控件:标签控件Tab Control 下)
上一节中鸡啄米讲了标签控件知识的上半部分,本节继续讲下半部分. 标签控件的创建 MFC为标签控件的操作提供了CTabCtrl类. 与之前的控件类似,创建标签控件可以在对话框模板中直接拖入Tab Con ...
- 调用spark API,监控任务的进度
我们现在需要监控datapre0这个任务每一次执行的进度,操作如下: 1. 如图所示,打开spark管理页面,找到对应的任务,点击任务名datapre0 2. 进去之后,获得对应IP和端口 3. 访 ...