Python中用函数作为返回值和实现闭包的教程


Posted in Python onApril 27, 2015

函数作为返回值

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。

我们来实现一个可变参数的求和。通常情况下,求和的函数是这样定义的:

def calc_sum(*args):
  ax = 0
  for n in args:
    ax = ax + n
  return ax

但是,如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数!

def lazy_sum(*args):
  def sum():
    ax = 0
    for n in args:
      ax = ax + n
    return ax
  return sum

当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:

>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function sum at 0x10452f668>

调用函数f时,才真正计算求和的结果:

>>> f()
25

在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

请再注意一点,当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数:

>>> f1 = lazy_sum(1, 3, 5, 7, 9)
>>> f2 = lazy_sum(1, 3, 5, 7, 9)
>>> f1==f2
False

f1()和f2()的调用结果互不影响。
闭包

注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。

另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。我们来看一个例子:

def count():
  fs = []
  for i in range(1, 4):
    def f():
       return i*i
    fs.append(f)
  return fs

f1, f2, f3 = count()

在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都返回了。

你可能认为调用f1(),f2()和f3()结果应该是1,4,9,但实际结果是:

>>> f1()
9
>>> f2()
9
>>> f3()
9

全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

>>> def count():
...   fs = []
...   for i in range(1, 4):
...     def f(j):
...       def g():
...         return j*j
...       return g
...     fs.append(f(i))
...   return fs
... 
>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9

缺点是代码较长,可利用lambda函数缩短代码。

Python 相关文章推荐
python获取标准北京时间的方法
Mar 24 Python
初步认识Python中的列表与位运算符
Oct 12 Python
使用python进行文本预处理和提取特征的实例
Jun 05 Python
Python输出\u编码将其转换成中文的实例
Dec 15 Python
在python3中pyqt5和mayavi不兼容问题的解决方法
Jan 08 Python
Python 中Django验证码功能的实现代码
Jun 20 Python
python面试题之列表声明实例分析
Jul 08 Python
pytorch载入预训练模型后,实现训练指定层
Jan 06 Python
keras CNN卷积核可视化,热度图教程
Jun 22 Python
Python操控mysql批量插入数据的实现方法
Oct 27 Python
让文件路径提取变得更简单的Python Path库
May 27 Python
python数据分析之单因素分析线性拟合及地理编码
Jun 25 Python
Python中利用sorted()函数排序的简单教程
Apr 27 #Python
Python中的filter()函数的用法
Apr 27 #Python
Python中的map()函数和reduce()函数的用法
Apr 27 #Python
PyMongo安装使用笔记
Apr 27 #Python
Windows下PyMongo下载及安装教程
Apr 27 #Python
Python操作MongoDB数据库PyMongo库使用方法
Apr 27 #Python
Python的函数的一些高阶特性
Apr 27 #Python
You might like
Could not load type System.ServiceModel.Activation.HttpModule解决办法
2012/12/29 PHP
Javascript 跨域访问解决方案
2009/02/14 Javascript
利用浏览器全屏api实现js全屏
2014/01/16 Javascript
理解javascript中DOM事件
2015/12/25 Javascript
详解Wondows下Node.js使用MongoDB的环境配置
2016/03/01 Javascript
AngularJs Javascript MVC 框架
2016/06/20 Javascript
Canvas 制作动态进度加载水球详解及实例代码
2016/12/09 Javascript
JavaScript中数组Array方法详解
2017/02/27 Javascript
JavaScript通过改变文字透明度实现的文字闪烁效果实例
2017/04/27 Javascript
vue上传图片组件编写代码
2017/07/26 Javascript
微信小程序简单的canvas裁剪图片功能详解
2019/07/12 Javascript
JS实现可用滑块滑动的缓动图代码
2019/09/01 Javascript
Node使用Selenium进行前端自动化操作的代码实现
2019/10/10 Javascript
file-loader打包图片文件时路径错误输出为[object-module]的解决方法
2020/01/03 Javascript
python笔记(1) 关于我们应不应该继续学习python
2012/10/24 Python
举例讲解Python程序与系统shell交互的方式
2015/04/09 Python
pandas值替换方法
2018/07/10 Python
NLTK 3.2.4 环境搭建教程
2018/09/19 Python
Python可迭代对象操作示例
2019/05/07 Python
python实现矩阵和array数组之间的转换
2019/11/29 Python
python 遗传算法求函数极值的实现代码
2020/02/11 Python
深入了解Python enumerate和zip
2020/07/16 Python
python如何删除列为空的行
2020/07/17 Python
德国Discount-Apotheke中文官网:DC德式康线上药房
2020/02/18 全球购物
入党申请书自我鉴定
2013/10/12 职场文书
交通法规咨询中心工作职责
2013/11/27 职场文书
工厂保洁员岗位职责
2013/12/04 职场文书
工程业务员岗位职责
2013/12/31 职场文书
学术诚信承诺书
2014/05/26 职场文书
会计专业自荐书
2014/07/08 职场文书
调研座谈会发言材料
2014/08/23 职场文书
学校开学标语
2014/10/06 职场文书
2014年民主评议党员工作总结
2014/12/02 职场文书
八年级历史教学反思
2016/02/19 职场文书
html5调用摄像头截图功能
2022/01/18 Javascript
Win10服务主机占用内存怎么办?Win10服务主机进程占用大量内存解决方法
2022/09/23 数码科技