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爬虫DNS解析缓存方法实例分析
Jun 02 Python
python爬虫 正则表达式使用技巧及爬取个人博客的实例讲解
Oct 20 Python
PyCharm 常用快捷键和设置方法
Dec 20 Python
在pandas中一次性删除dataframe的多个列方法
Apr 10 Python
Django2.1.3 中间件使用详解
Nov 26 Python
Python3内置模块pprint让打印比print更美观详解
Jun 02 Python
在PYQT5中QscrollArea(滚动条)的使用方法
Jun 14 Python
keras中的backend.clip用法
May 22 Python
python实现斗地主分牌洗牌
Jun 22 Python
将不规则的Python多维数组拉平到一维的方法实现
Jan 11 Python
Django中session进行权限管理的使用
Jul 09 Python
python 单机五子棋对战游戏
Apr 28 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
收音机鉴频器对声音的影响和频偏分析
2021/03/02 无线电
Smarty Foreach 使用说明
2010/03/23 PHP
PHP-FPM实现性能优化
2016/03/31 PHP
Yii2中使用join、joinwith多表关联查询
2016/06/30 PHP
php魔术方法功能与用法实例分析
2016/10/19 PHP
PHP验证码无法显示的原因及解决办法
2017/08/11 PHP
Extjs 几个方法的讨论
2010/01/28 Javascript
javascript动态加载实现方法一
2012/08/22 Javascript
jQuery操作表单常用控件方法小结
2015/03/23 Javascript
JQuery中模拟image的ajaxPrefilter与ajaxTransport处理
2015/06/19 Javascript
常用的Javascript数据验证插件
2015/08/04 Javascript
浅谈javascript中的Function和Arguments
2016/08/30 Javascript
微信小程序 网络API发起请求详解
2016/11/09 Javascript
JS实现图片上传预览功能
2016/11/21 Javascript
基于JavaScript实现滑动门效果
2017/03/16 Javascript
js自定义trim函数实现删除两端空格功能
2018/02/09 Javascript
layui多图上传实现删除功能的例子
2019/09/23 Javascript
微信小程序scroll-view隐藏滚动条的方法详解
2020/03/25 Javascript
[07:49]2014DOTA2国际邀请赛 Newbee夺冠后采访xiao8坦言奖金会上交
2014/07/23 DOTA
[01:20:38]完美世界DOTA2联赛 GXR vs IO 第一场 11.07
2020/11/09 DOTA
Scrapy爬虫实例讲解_校花网
2017/10/23 Python
Python实现读取Properties配置文件的方法
2018/03/29 Python
python 使用while写猜年龄小游戏过程解析
2019/10/07 Python
Python小程序 控制鼠标循环点击代码实例
2019/10/08 Python
python验证码图片处理(二值化)
2019/11/01 Python
html5指南-3.如何实现html元素拖拽功能
2013/01/07 HTML / CSS
德国最大的网上鞋店之一:Schuhe24.de
2017/06/10 全球购物
美国婴儿用品店:Babies”R”Us
2017/10/12 全球购物
德国高尔夫商店:Par71.de
2020/11/29 全球购物
优秀学生干部个人的自我评价
2013/10/04 职场文书
员工年终演讲稿
2014/01/03 职场文书
中式餐厅创业计划书范文
2014/01/23 职场文书
护士自我鉴定怎么写
2014/02/07 职场文书
高三复习计划
2015/01/19 职场文书
自我评价优缺点范文
2015/03/11 职场文书
房地产公司财务总监岗位职责
2015/04/03 职场文书