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 ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
Jun 10 Python
编程语言Python的发展史
Sep 26 Python
Python函数可变参数定义及其参数传递方式实例详解
May 25 Python
python基于BeautifulSoup实现抓取网页指定内容的方法
Jul 09 Python
python基于pyDes库实现des加密的方法
Apr 29 Python
python 构造三维全零数组的方法
Nov 12 Python
python+flask实现API的方法
Nov 21 Python
python实现读取excel文件中所有sheet操作示例
Aug 09 Python
pyinstaller打包程序exe踩过的坑
Nov 19 Python
Spring http服务远程调用实现过程解析
Jun 11 Python
python获得命令行输入的参数的两种方式
Nov 02 Python
Python 如何将integer转化为罗马数(3999以内)
Jun 05 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
linux下 C语言对 php 扩展
2008/12/14 PHP
php程序效率优化的一些策略小结
2010/07/17 PHP
浏览器关闭后,能继续执行的php函数(ignore_user_abort)
2012/08/01 PHP
php socket通信(tcp/udp)实例分析
2016/02/14 PHP
PHP中ID设置自增后不连续的原因分析及解决办法
2016/08/21 PHP
PHP编程文件处理类SplFileObject和SplFileInfo用法实例分析
2017/07/22 PHP
$()JS小技巧
2007/07/21 Javascript
JavaScript Chart 插件整理
2010/06/18 Javascript
jQuery Tools Dateinput使用介绍
2012/07/14 Javascript
JavaScript加入收藏夹功能(兼容IE、firefox、chrome)
2014/05/05 Javascript
详细分析使用AngularJS编程中提交表单的方式
2015/06/19 Javascript
javascript中setAttribute兼容性用法分析
2016/12/12 Javascript
vue中各组件之间传递数据的方法示例
2017/07/27 Javascript
微信小程序动态生成二维码的实现代码
2018/07/25 Javascript
vue中关闭eslint的方法分析
2018/08/04 Javascript
微信小程序身份证验证方法实现详解
2019/06/28 Javascript
Vue使用vue-recoure + http-proxy-middleware + vuex配合promise实现基本的跨域请求封装
2019/10/21 Javascript
VUE DEMO之模拟登录个人中心页面之间数据传值实例
2019/10/31 Javascript
《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析
2020/04/07 Javascript
JavaScript常用工具函数库汇总
2020/09/17 Javascript
js 数据类型判断的方法
2020/12/03 Javascript
[00:42]《辉夜杯》—职业组预选赛12月3日15点 正式打响
2015/12/03 DOTA
编写简单的Python程序来判断文本的语种
2015/04/07 Python
jupyter安装小结
2016/03/13 Python
Python中列表、字典、元组数据结构的简单学习笔记
2016/03/20 Python
Python实现定时执行任务的三种方式简单示例
2019/03/30 Python
TensorFlow tf.nn.conv2d实现卷积的方式
2020/01/03 Python
介绍一下JMS编程步骤
2015/09/22 面试题
关于毕业的中学校园广播稿
2014/01/26 职场文书
优秀教师演讲稿
2014/05/06 职场文书
赔偿协议书范本
2014/09/12 职场文书
小学教师师德师风个人整改措施
2014/09/18 职场文书
2014年艾滋病防治工作总结
2014/12/10 职场文书
全陪导游词
2015/02/04 职场文书
《乘法分配律》教学反思
2016/02/24 职场文书
给原生html中添加水印遮罩层的实现示例
2021/04/02 Javascript