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使用bs4获取58同城城市分类的方法
Jul 08 Python
完美解决Python 2.7不能正常使用pip install的问题
Jun 12 Python
Pycharm无法显示动态图片的解决方法
Oct 28 Python
不到40行代码用Python实现一个简单的推荐系统
May 10 Python
python 定时器每天就执行一次的实现代码
Aug 14 Python
python集合的创建、添加及删除操作示例
Oct 08 Python
Python爬取12306车次信息代码详解
Aug 12 Python
Django-Scrapy生成后端json接口的方法示例
Oct 06 Python
Python运算符+与+=的方法实例
Feb 18 Python
一文搞懂如何实现Go 超时控制
Mar 30 Python
利用Python网络爬虫爬取各大音乐评论的代码
Apr 13 Python
使用python生成大量数据写入es数据库并查询操作(2)
Sep 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
php简单对象与数组的转换函数代码(php多层数组和对象的转换)
2011/05/18 PHP
PHP发明人谈MVC和网站设计架构 貌似他不支持php用mvc
2011/06/04 PHP
PHP Class&amp;Object -- 解析PHP实现二叉树
2013/06/25 PHP
PHP系统命令函数使用分析
2013/07/05 PHP
PHP使Laravel为JSON REST API返回自定义错误的问题
2018/10/16 PHP
六款帮助你实现惊艳视差滚动效果的jQuery插件
2012/09/14 Javascript
JS生成随机字符串的多种方法
2014/06/10 Javascript
js实现文本框支持加减运算的方法
2015/08/19 Javascript
JS控制弹出悬浮窗口(一览画面)的实例代码
2016/05/30 Javascript
Angular4学习教程之DOM属性绑定详解
2018/01/04 Javascript
JavaScript轮播停留效果的实现思路
2018/05/24 Javascript
jQuery事件绑定和解绑、事件冒泡与阻止事件冒泡及弹出应用示例
2019/05/13 jQuery
JS面试题中深拷贝的实现讲解
2020/05/07 Javascript
js操作两个json数组合并、去重,以及删除某一项元素
2020/09/22 Javascript
[09:40]DAC2018 4.5 SOLO赛 MidOne vs Miracle
2018/04/06 DOTA
布同自制Python函数帮助查询小工具
2011/03/13 Python
python使用正则表达式检测密码强度源码分享
2014/06/11 Python
Python requests模块实例用法
2019/02/11 Python
django 中使用DateTime常用的时间查询方式
2019/12/03 Python
python扫描线填充算法详解
2020/02/19 Python
基于Python生成个性二维码过程详解
2020/03/05 Python
详解python3类型注释annotations实用案例
2021/01/20 Python
CSS3+Sprite实现僵尸行走动画特效源码
2016/01/27 HTML / CSS
Html5+CSS3+EL表达式问题小结
2020/12/19 HTML / CSS
美国护肤咨询及美容产品电商:Askderm
2017/02/24 全球购物
Araks官网:纽约内衣品牌
2020/10/15 全球购物
法雷奥SQA(electric)面试问题
2016/01/23 面试题
周年庆典主持词
2014/04/02 职场文书
小学生学雷锋演讲稿
2014/04/25 职场文书
单位承诺书格式
2014/05/21 职场文书
刑事和解协议书范本
2014/11/19 职场文书
学校节水倡议书
2015/04/29 职场文书
幼儿园安全教育月活动总结
2015/05/08 职场文书
交心谈心活动总结
2015/05/11 职场文书
学雷锋主题班会教案
2015/08/13 职场文书
vue+spring boot实现校验码功能
2021/05/27 Vue.js