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 相关文章推荐
linux环境下python中MySQLdb模块的安装方法
Jun 16 Python
django 2.0更新的10条注意事项总结
Jan 05 Python
Python获取系统所有进程PID及进程名称的方法示例
May 24 Python
Python3.5基础之函数的定义与使用实例详解【参数、作用域、递归、重载等】
Apr 26 Python
python多进程间通信代码实例
Sep 30 Python
python3中rank函数的用法
Nov 27 Python
python 字典访问的三种方法小结
Dec 05 Python
python 使用opencv 把视频分割成图片示例
Dec 12 Python
Python基于pyecharts实现关联图绘制
Mar 27 Python
scrapy中如何设置应用cookies的方法(3种)
Sep 22 Python
Python 将代码转换为可执行文件脱离python环境运行(步骤详解)
Jan 25 Python
利用Python网络爬虫爬取各大音乐评论的代码
Apr 13 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面向对象编程快速入门
2006/12/14 PHP
php使HTML标签自动补全闭合函数代码
2012/10/04 PHP
在wamp集成环境下升级php版本(实现方法)
2013/07/01 PHP
Laravel与CI框架中截取字符串函数
2016/05/08 PHP
浅谈php中curl、fsockopen的应用
2016/12/10 PHP
PHP实现的DES加密解密封装类完整实例
2017/04/29 PHP
PHP面向对象中new self()与 new static()的区别浅析
2017/08/17 PHP
详解提高使用Java反射的效率方法
2019/04/29 PHP
读jQuery之十三 添加事件和删除事件的核心方法
2011/08/23 Javascript
在javascript中关于节点内容加强
2013/04/11 Javascript
jquery中$(#form :input)与$(#form input)的区别
2014/08/18 Javascript
jQuery插件jRumble实现网页元素抖动
2015/06/05 Javascript
AngularJS实现按钮提示与点击变色效果
2016/09/07 Javascript
vue.js开发环境搭建教程
2017/05/04 Javascript
微信小程序 支付功能(前端)的实现
2017/05/24 Javascript
详解Vue中watch的高级用法
2018/05/02 Javascript
让webpack+vue-cil项目不再自动打开浏览器的方法
2018/09/27 Javascript
浅谈js闭包理解
2019/03/28 Javascript
js实现踩五彩块游戏
2020/02/08 Javascript
js瀑布流布局的实现
2020/06/28 Javascript
Python获取运行目录与当前脚本目录的方法
2015/06/01 Python
python+pyqt实现12306图片验证效果
2017/10/25 Python
对python3标准库httpclient的使用详解
2018/12/18 Python
20行Python代码实现一款永久免费PDF编辑工具的实现
2020/08/27 Python
Python类成员继承重写的实现
2020/09/16 Python
详解CSS3中常用的样式【基本文本和字体样式】
2020/10/20 HTML / CSS
Lampegiganten丹麦:欧洲领先的照明网上商店
2018/04/25 全球购物
波兰品牌鞋履在线商店:Eastend.pl
2020/01/11 全球购物
Penhaligon’s英国官网:成立于1870年的英国香水制造商
2021/02/18 全球购物
什么是事务?事务有哪些性质?
2012/03/11 面试题
如何利用find命令查找文件
2015/02/07 面试题
外贸主管求职简历的自我评价
2013/10/23 职场文书
工作自荐信
2013/12/11 职场文书
英文自荐信常用句子
2014/03/26 职场文书
奶茶店创业计划书
2014/08/14 职场文书
使用CSS3实现按钮悬停闪烁动态特效代码
2021/08/30 HTML / CSS