原文

函数作为返回值

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

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

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

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

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,但实际结果是:

全部都是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

再看看结果:

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

python 之闭包的更多相关文章

  1. Python的闭包

    Python的闭包 闭包概念都是一样的,实现机制一样,看看下面的代码是不是和javascript很像 def generate_counter(): cnt = [0] def count_one() ...

  2. Python之闭包

    Python之闭包 我们知道,在装饰器中,可以在函数体内创建另外一个函数,例如: def makebold(fn): def wrapped(): return "<b>&quo ...

  3. Python函数编程——闭包和装饰器

    Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个 ...

  4. python中闭包详解

    谈谈自己的理解:python中闭包,闭包的实质   闭包这个概念好难理解,身边朋友们好多都稀里糊涂的,稀里糊涂的林老冷希望写下这篇文章能够对稀里糊涂的伙伴们有一些帮助~ 请大家跟我理解一下,如果在一个 ...

  5. python的闭包与装饰器

    原文发表在我的博客主页,转载请注明出处 前言 如果把python当作脚本语言,每次就是写个几十行上百行来处理数据的话,装饰器也许不是很必要,但是如果要开发一个大型系统,装饰器是躲不开的,最开始体会ry ...

  6. python的闭包以及闭包在设计里的意图和作用

    def test(func): print func(3,4) test(lambda x,y : x+y) test(lambda x,y : x-y) 这是python的一种闭包写法,他的设计意图 ...

  7. python之闭包与装饰器

    python闭包与装饰器 闭包 在函数内部定义的函数包含对外部的作用域,而不是全局作用域名字的引用,这样的函数叫做闭包函数. 示例: #-------------------------------- ...

  8. 【Python】 闭包&装饰器

    python中的函数本身就是对象,所以可以作为参数拿来传递.同时其允许函数的层级嵌套定义,使得灵活性大大增加. 闭包 闭包的定义:将函数的语句块与其运行所需要的环境打包到一起,得到的就是闭包对象.比如 ...

  9. 谈谈自己的理解:python中闭包,闭包的实质

    闭包这个概念好难理解,身边朋友们好多都稀里糊涂的,稀里糊涂的林老冷希望写下这篇文章能够对稀里糊涂的伙伴们有一些帮助~ 请大家跟我理解一下,如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内 ...

  10. 【python】闭包

    一.闭包满足的条件 闭包 = 内部函数 + 定义函数的环境 条件一 : 内部函数 条件二: 外部环境的变量 二.实战 def outer(): x = 10 y = 20 def inner(): p ...

随机推荐

  1. MyBatis介绍及使用

    一.介绍: 1.MyBatis实际上是Ibatis3.0版本以后的持久化层框架[也就是和数据库打交道的框架]! 2.和数据库打交道的技术有: 原生的JDBC技术--->Spring的JdbcTe ...

  2. idea中文输入问题

    desc: idea2017.3.4输入中文,光标不跟随. 解决方案:

  3. 品味ZooKeeper之Watcher机制_2

    品味ZooKeeper之Watcher机制 本文思维导图如下: 前言 Watcher机制是zookeeper最重要三大特性数据节点Znode+Watcher机制+ACL权限控制中的其中一个,它是zk很 ...

  4. 没有上司的舞会 树形dp

    题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri, ...

  5. CBoard 图表布局浅析

    这两天想了解下图表布局,对前端Angular不熟悉,Java也不熟悉.只能靠经验摸索查找,所以把过程简单记录,生怕忘记.首先是打开图表,发现位置指向 /config/widget, 然后用IDEA搜索 ...

  6. REST模式中HTTP请求方法(GET,POST,PUT,DELETE)

    一直在测试REST模式的WEB SERVICE接口,客户端的HTTP的请求方式一般分为四种:GET.POST.PUT.DELETE,这四种请求方式有什么不同呢.简单的说,GET就是获取资源,POST就 ...

  7. C. Enlarge GCD Codeforces Round #511 (Div. 2)【数学】

    题目: Mr. F has nn positive integers, a1,a2,…,an. He thinks the greatest common divisor of these integ ...

  8. HDU - 2087 求不可重复字符串的匹配次数

    只要KMP里对f[i]进行限制即可 /*H E A D*/ int nxt[maxn],f[maxn],ans; char T[maxn],P[maxn]; void buildNext(){ int ...

  9. Action执行时间过滤器

    public class AccessStatisticsAttribute : ActionFilterAttribute { /// <summary> /// log4net 日志 ...

  10. [转] Android:用GSON 五招之内搞定任何JSON数组

    [From] http://www.open-open.com/lib/view/open1472632967912.html 写在前面 关于GSON的入门级使用,这里就不提了,如有需要可以看这篇博文 ...