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 13 Python
python扫描proxy并获取可用代理ip的实例
Aug 07 Python
Pandas 对Dataframe结构排序的实现方法
Apr 10 Python
Pycharm设置去除显示的波浪线方法
Oct 28 Python
Python数据结构与算法(几种排序)小结
Jun 22 Python
seek引发的python文件读写的问题及解决
Jul 26 Python
python模拟鼠标点击和键盘输入的操作
Aug 04 Python
Python generator生成器和yield表达式详解
Aug 08 Python
python3实现微型的web服务器
Sep 03 Python
Python字符串格式化输出代码实例
Nov 22 Python
记录一下scrapy中settings的一些配置小结
Sep 28 Python
python使用requests库爬取拉勾网招聘信息的实现
Nov 20 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和ACCESS写聊天室(六)
2006/10/09 PHP
ASP.NET jQuery 实例13 原创jQuery文本框字符限制插件-TextArea Counter
2012/02/03 Javascript
node.js中的http.createServer方法使用说明
2014/12/14 Javascript
jQuery入门基础知识学习指南
2015/08/14 Javascript
node.js中module.exports与exports用法上的区别
2016/09/02 Javascript
用js控件div的滚动条,让它在内容更新时自动滚到底部的实现方法
2016/10/27 Javascript
Javascript实现信息滚动效果
2017/05/18 Javascript
webpack构建的详细流程探底
2018/01/08 Javascript
详解plotly.js 绘图库入门使用教程
2018/02/23 Javascript
深入理解Vue 的钩子函数
2018/09/05 Javascript
Vue表单控件数据绑定方法详解
2020/02/05 Javascript
react组件基本用法示例小结
2020/04/27 Javascript
Vue如何提升首屏加载速度实例解析
2020/06/25 Javascript
[22:59]VGJ.S vs VG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
python类继承与子类实例初始化用法分析
2015/04/17 Python
python 获取当天每个准点时间戳的实例
2018/05/22 Python
关于Django ForeignKey 反向查询中filter和_set的效率对比详解
2018/12/15 Python
利用python和ffmpeg 批量将其他图片转换为.yuv格式的方法
2019/01/08 Python
用python爬取历史天气数据的方法示例
2019/12/30 Python
python代码如何实现余弦相似性计算
2020/02/09 Python
Django Admin后台添加数据库视图过程解析
2020/04/01 Python
html5-websocket基于远程方法调用的数据交互实现
2012/12/04 HTML / CSS
解决HTML5中滚动到底部的事件问题
2019/08/22 HTML / CSS
英国最大的香水商店:The Fragrance Shop
2018/07/06 全球购物
建龙钢铁面试总结
2014/04/15 面试题
Unix/Linux开发面试题
2016/08/16 面试题
会计电算化个人求职信范文
2014/01/24 职场文书
丑小鸭教学反思
2014/02/03 职场文书
企业内控岗位的职责
2014/02/07 职场文书
《小石潭记》教学反思
2014/02/13 职场文书
聚美优品广告词改编
2014/03/14 职场文书
银行奉献演讲稿
2014/09/16 职场文书
加强作风建设演讲稿
2014/10/24 职场文书
投资公司董事长岗位职责
2015/04/16 职场文书
宪法宣传标语100条
2019/10/15 职场文书
一篇文章看懂MySQL主从复制与读写分离
2021/11/07 MySQL