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爬虫抓取手机APP的传输数据
Jan 22 Python
Python使用爬虫猜密码
Feb 19 Python
利用Python破解斗地主残局详解
Jun 30 Python
flask中使用蓝图将路由分开写在不同文件实例解析
Jan 19 Python
详解python中的线程
Feb 10 Python
python list格式数据excel导出方法
Oct 31 Python
Python叠加两幅栅格图像的实现方法
Jul 05 Python
python使用协程实现并发操作的方法详解
Dec 27 Python
Python + selenium + crontab实现每日定时自动打卡功能
Mar 31 Python
django中related_name的用法说明
May 20 Python
QML实现钟表效果
Jun 02 Python
Pycharm自动添加文件头注释和函数注释参数的方法
Oct 23 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
BBS(php &amp; mysql)完整版(一)
2006/10/09 PHP
如何在PHP中进行身份认证
2006/10/09 PHP
PHP获取MSN好友列表类的实现代码
2013/06/23 PHP
Apache实现Web Server负载均衡详解(不考虑Session版)
2013/07/05 PHP
完整删除ecshop中获取店铺信息的API
2014/12/24 PHP
PHP使用PHPexcel导入导出数据的方法
2015/11/14 PHP
PHP入门教程之面向对象基本概念实例分析
2016/09/11 PHP
jquery ajax传递中文参数乱码问题及解决方法说明
2014/02/07 Javascript
JSON简介以及用法汇总
2016/02/21 Javascript
JS给Array添加是否包含字符串的简单方法
2016/10/29 Javascript
给easyui的datebox控件添加清空按钮的实现方法
2016/11/09 Javascript
Bootstrap源码解读标签、徽章、缩略图和警示框(8)
2016/12/26 Javascript
js放大镜放大购物图片效果
2017/01/18 Javascript
ES6使用let命令更简单的实现块级作用域实例分析
2017/03/31 Javascript
JS实现带动画的回到顶部效果
2017/12/28 Javascript
Vue子组件向父组件通信与父组件调用子组件中的方法
2018/06/22 Javascript
vuejs+element UI点击编辑表格某一行时获取内容填入表单的示例
2018/10/31 Javascript
[14:03]2017DOTA2亚洲邀请赛开幕式:12神兵演绎水墨中华
2017/04/01 DOTA
Python操作Mysql实例代码教程在线版(查询手册)
2013/02/18 Python
python编写暴力破解FTP密码小工具
2014/11/19 Python
Python玩转PDF的各种骚操作
2019/05/06 Python
python单向链表的基本实现与使用方法【定义、遍历、添加、删除、查找等】
2019/10/24 Python
Python计算不规则图形面积算法实现解析
2019/11/22 Python
解决Jupyter NoteBook输出的图表太小看不清问题
2020/04/16 Python
CSS实现鼠标滑过鼠标点击代码写法
2016/12/26 HTML / CSS
优秀毕业自我鉴定
2014/02/15 职场文书
自考毕业自我鉴定
2014/03/18 职场文书
远程网络教育毕业生自我鉴定
2014/04/14 职场文书
法学求职信
2014/06/22 职场文书
2014乡镇领导班子四风对照检查材料思想汇报
2014/10/05 职场文书
答辩状格式范本
2015/05/22 职场文书
2015年领导班子工作总结
2015/05/23 职场文书
Html5新增了哪些功能
2021/04/16 HTML / CSS
CSS 还能这样玩?奇思妙想渐变的艺术
2021/04/27 HTML / CSS
Python中Cookies导出某站用户数据的方法
2021/05/17 Python
教你利用python实现企业微信发送消息
2021/05/23 Python