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通过ftplib登录到ftp服务器的方法
May 08 Python
Python IDLE 错误:IDLE''s subprocess didn''t make connection 的解决方案
Feb 13 Python
Python编写一个闹钟功能
Jul 11 Python
快速了解Python中的装饰器
Jan 11 Python
基于windows下pip安装python模块时报错总结
Jun 12 Python
Python过滤txt文件内重复内容的方法
Oct 21 Python
对Python3使运行暂停的方法详解
Feb 18 Python
浅谈Python 递归算法指归
Aug 22 Python
Python bisect模块原理及常见实例
Jun 17 Python
python开发实时可视化仪表盘的示例
May 07 Python
Python爬虫之用Xpath获取关键标签实现自动评论盖楼抽奖(二)
Jun 07 Python
Python+OpenCV实现在图像上绘制矩形
Mar 21 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管理内存函数 memory_get_usage()使用介绍
2012/09/23 PHP
PHP中的密码加密的解决方案总结
2016/10/26 PHP
在laravel中实现将查询的对象转换为多维数组的函数
2019/10/21 PHP
深入解析PHP底层机制及相关原理
2020/12/11 PHP
BOOM vs RR BO3 第二场2.13
2021/03/10 DOTA
NiftyCube——轻松实现圆角边框
2007/02/20 Javascript
发布BlueShow v1.0 图片浏览器(类似lightbox)blueshow.js 打包下载
2007/07/21 Javascript
jQuery 跨域访问问题解决方法
2009/12/02 Javascript
说明你的Javascript技术很烂的五个原因
2011/04/26 Javascript
javascript中的缓动效果实现程序
2012/12/29 Javascript
window resize和scroll事件的基本优化思路
2014/04/29 Javascript
javascript文本框内输入文字倒计数的方法
2015/02/24 Javascript
jQuery源码分析之Callbacks详解
2015/03/13 Javascript
概述jQuery中的ajax方法
2016/12/16 Javascript
AngularJS表单基本操作
2017/01/09 Javascript
React Native AsyncStorage本地存储工具类
2017/10/24 Javascript
详解如何探测小程序返回到webview页面
2019/05/14 Javascript
vue-video-player视频播放器使用配置详解
2020/10/23 Javascript
Python中对象的引用与复制代码示例
2017/12/04 Python
利用Python2下载单张图片与爬取网页图片实例代码
2017/12/25 Python
深入理解Python爬虫代理池服务
2018/02/28 Python
Python3.6日志Logging模块简单用法示例
2018/06/14 Python
用django设置session过期时间的方法解析
2019/08/05 Python
Python绘图实现显示中文
2019/12/04 Python
django创建css文件夹的具体方法
2020/07/31 Python
大一学生的职业生涯规划书范文
2014/01/19 职场文书
理财投资建议书
2014/03/12 职场文书
毕业自我鉴定书
2014/03/24 职场文书
建设工地安全标语
2014/06/07 职场文书
优秀教师先进材料
2014/12/16 职场文书
2015年党支部公开承诺书
2015/01/22 职场文书
幼儿园音乐教学反思
2016/02/18 职场文书
导游词之嵊泗列岛
2019/10/30 职场文书
left join、inner join、right join的区别
2021/04/05 MySQL
web前端之css水平居中代码解析
2021/05/20 HTML / CSS
Python实现简单的猜单词
2021/06/15 Python