python中闭包Closure函数作为返回值的方法示例


Posted in Python onDecember 17, 2017

前言

首先看看闭包的概念:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,闭包是由函数和与其相关的引用环境组合而成的实体。

一、函数作为返回值

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。

>>> def lazy_sum(*args):
...  def sum():
...   ax = 0
...   for n in args:
...    ax = ax + n
...   return ax
...  return sum
... 
>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function lazy_sum.<locals>.sum at 0x1014ae730>
>>> f()
25

当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数:

>>> f1 = lazy_sum(1, 3, 5, 7)
>>> f2 = lazy_sum(1, 3, 5, 7)
>>> f1
<function lazy_sum.<locals>.sum at 0x1014ae8c8>
>>> f2
<function lazy_sum.<locals>.sum at 0x1014ae7b8>
>>> f1 == f2
False

二、闭包

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

简单的说,这种内部函数可以使用外部函数变量的行为,就叫闭包

在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。

返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

>>> def count():
...  fs = []
...  for i in range(1, 4):
...   def f():
...    return i * i
...   fs.append(f)
...  return fs
... 
>>> f1, f2, f3 = count()
>>> f1()
9
>>> f2()
9
>>> f3()
9

全部都是9!原因就在于返回的函数引用了循环变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

>>> def count():
...  def f(j):
...   def g():
...    return j * j
...   return g
...  fs = []
...  for i in range(1, 4):
...   fs.append(f(i))
...  return fs
... 
>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
使用Python读写文本文件及编写简单的文本编辑器
Mar 11 Python
基于hashlib模块--加密(详解)
Jun 21 Python
分数霸榜! python助你微信跳一跳拿高分
Jan 08 Python
windows下python安装小白入门教程
Sep 18 Python
对python中数组的del,remove,pop区别详解
Nov 07 Python
pthon贪吃蛇游戏详细代码
Jan 27 Python
Python爬虫图片懒加载技术 selenium和PhantomJS解析
Sep 18 Python
通过字符串导入 Python 模块的方法详解
Oct 27 Python
python next()和iter()函数原理解析
Feb 07 Python
python实现感知机模型的示例
Sep 30 Python
matplotlib绘制鼠标的十字光标的实现(内置方式)
Jan 06 Python
彻底解决pip下载pytorch慢的问题方法
Mar 01 Python
django模板语法学习之include示例详解
Dec 17 #Python
详解python string类型 bytes类型 bytearray类型
Dec 16 #Python
python使用os.listdir和os.walk获得文件的路径的方法
Dec 16 #Python
python读取与写入csv格式文件的示例代码
Dec 16 #Python
浅谈用VSCode写python的正确姿势
Dec 16 #Python
numpy中索引和切片详解
Dec 15 #Python
Python实现简单网页图片抓取完整代码实例
Dec 15 #Python
You might like
PHP正则的Unknown Modifier错误解决方法
2010/03/02 PHP
PHP面向对象概念
2011/11/06 PHP
php清除和销毁session的方法分析
2015/03/19 PHP
使用laravel指定日志文件记录任意日志
2019/10/17 PHP
Cookie跨域问题解决方案代码示例
2020/11/24 PHP
javascript中检测变量的类型的代码
2010/12/28 Javascript
js确定对象类型方法
2012/03/30 Javascript
jquery获取div宽度的实现思路与代码
2013/01/13 Javascript
JavaScript创建类/对象的几种方式概述及实例
2013/05/06 Javascript
bootstrap布局中input输入框右侧图标点击功能
2016/05/16 Javascript
AngularJs bootstrap搭载前台框架——准备工作
2016/09/01 Javascript
微信小程序使用modal组件弹出对话框功能示例
2017/11/29 Javascript
用Axios Element实现全局的请求loading的方法
2018/03/15 Javascript
nodejs log4js 使用详解
2019/05/31 NodeJs
Vue动态生成表格的行和列
2019/07/18 Javascript
vue 如何从单页应用改造成多页应用
2020/10/23 Javascript
Python中关于字符串对象的一些基础知识
2015/04/08 Python
深入解析Python的Tornado框架中内置的模板引擎
2016/07/11 Python
浅谈Python黑帽子取代netcat
2018/02/10 Python
Python图像处理之直线和曲线的拟合与绘制【curve_fit()应用】
2018/12/26 Python
详解python中的线程与线程池
2019/05/10 Python
Python日志:自定义输出字段 json格式输出方式
2020/04/27 Python
python3.6使用SMTP协议发送邮件
2020/05/20 Python
pyCharm 实现关闭代码检查
2020/06/09 Python
详解基于python的图像Gabor变换及特征提取
2020/10/26 Python
Python爬虫之Selenium实现窗口截图
2020/12/04 Python
推荐一些比较有用的css3新属性
2014/11/11 HTML / CSS
详解CSS3的图层阴影和文字阴影效果使用
2016/06/09 HTML / CSS
制药工程专业毕业生推荐信
2013/12/24 职场文书
大型车展策划方案
2014/02/01 职场文书
业务部门经理岗位职责
2014/02/23 职场文书
经理助理岗位职责
2014/03/05 职场文书
2014年民主评议党员个人总结
2014/09/24 职场文书
2015年采购部工作总结
2015/04/23 职场文书
2016年庆“七一”主题党日活动总结
2016/04/05 职场文书
CSS3 制作的书本翻页特效
2021/04/13 HTML / CSS