函数作为返回值

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

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 lazy_sum.<locals>.sum at 0x101c6ed90>

调用函数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()结果应该是149,但实际结果是:

>>> 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)) # f(i)立刻被执行,因此i的当前值被传入f()
return fs

再看看结果:

>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9

Python实用笔记 (13)函数式编程——返回函数的更多相关文章

  1. python学习笔记011——函数式编程

    1 函数式编程 面向对象 ,面向过程 ,函数式编程 侧重函数的作用,注重函数结果的传递 函数可以被赋值,也可以接受其他的值 2 函数式编程特点 1.函数是一等公民 与其他变量一样,可以赋值和被赋值,可 ...

  2. Python基础笔记:函数式编程:高阶函数、返回函数、匿名函数

    高阶函数 高阶函数:一个函数可以接收另一个函数作为参数 或 一个函数可以返回一个函数作为返回值,这种函数称之为高阶函数. #函数 add 接收 f 函数作为参数 >>> def ad ...

  3. python学习笔记1 -- 函数式编程之高阶函数 使用函数作为返回值

    使用函数作为返回值,看起来就很高端有木有,前面了解过函数名本身就是一个变量,就比如abs()函数,abs只是变量名,而abs()才是函数调用,那么我们如果把ads这个变量作为返回值返回会怎么样呢,这就 ...

  4. python函数式编程——返回函数

    1.函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 2.闭包 注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还 ...

  5. [Python3] 036 函数式编程 返回函数

    目录 函数式编程 之 返回函数 1. 引子 2. 闭包 closure 函数式编程 之 返回函数 函数可以返回具体的值 也可以返回一个函数作为结果 1. 引子 1.1 定义一个普通函数 >> ...

  6. Python学习笔记之函数式编程

    python中的高阶函数 高阶函数就是 变量名指向函数,下面代码中的变量abs其实是一个函数,返回数字的绝对值,如abs(-10) 返回 10 def add(x,y,f): return f(x) ...

  7. python学习笔记(六) 函数式编程

    一 函数对象 函数同样可以作为对象复制给一个变量,如下: f = abs; print(f(-10)) f = 'abs'; print(f) def add(a,b,f): return f(a) ...

  8. Python学习笔记6 函数式编程_20170619

    廖雪峰python3学习笔记: # 高阶函数 将函数作为参数传入,这样的函数就是高阶函数(有点像C++的函数指针) def add(x, y): return x+y def mins(x, y): ...

  9. Python学习笔记(九)返回函数

    摘抄:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318352367 ...

随机推荐

  1. [06]HTML基础之表单标签

    1. <form>标签 表单容器,指定method属性和action属性是个良好的习惯. <form methor="POST" action="htt ...

  2. Myeclipse新建工作空间配置

    之前跟着尚硅谷JavaWeb视频学习,现在总结一下Myeclipse新建工作空间配置 Windows按钮下的Preferences 1. General -->   Workspace --&g ...

  3. JAVASE(十一) 高级类特性: abstract 、模板模式、interface、内部类、枚举、注解

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.关键字 abstract 1.1.abstract可以修饰:类,方法 1.2.abstract修饰方 ...

  4. Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)

    试题 算法训练 猴子吃包子 问题描述 从前,有一只吃包子很厉害的猴子,它可以吃无数个包子,但是,它吃不同的包子速度也不同:肉包每秒钟吃x个:韭菜包每秒钟吃y个:没有馅的包子每秒钟吃z个:现在有x1个肉 ...

  5. Java实现 蓝桥杯VIP 算法提高 勾股数

    算法提高 勾股数 时间限制:1.0s 内存限制:256.0MB 问题描述 勾股数是一组三个自然数,a < b < c,以这三个数为三角形的三条边能够形成一个直角三角形 输出所有a + b ...

  6. Linux权限管理命令chown、chgrp、umask详解

    命令chown详解 命令chown,所在路径为: 可以看到,这个命令的路径为:/usr/bin/chown ,所以它的执行权限是所有用户 命令的基本功能是改变文件或目录的所有者(只有root可以进行, ...

  7. PAT 统计同成绩学生

    本题要求读入 N 名学生的成绩,将获得某一给定分数的学生人数输出. 输入格式: 输入在第 1 行给出不超过 105 的正整数 N,即学生总人数.随后一行给出 N 名学生的百分制整数成绩,中间以空格分隔 ...

  8. unittest单元测试框架入门及应用

    一.简介 unittest是Python单元测试框架.unittest它支持自动化测试,在测试中使用setup(初始化)和shutdown(关闭销毁)操作,组织测试 用例为套件(批量运行),以及把测试 ...

  9. akka-typed(4) - EventSourcedBehavior in action

    前面提到过,akka-typed中较重要的改变是加入了EventSourcedBehavior.也就是说增加了一种专门负责EventSource模式的actor, 最终和其它种类的actor一道可以完 ...

  10. GitHub 热点速览 Vol.23:前后端最佳实践

    作者:HelloGitHub-小鱼干 摘要:最佳实践,又名 best-practices,是 GitHub 常见的项目名,也是本周 Trending 关键词.25 年 Python 开发经验的 Dav ...