python 闭包 Closure 函数作为返回值

一、函数作为返回值

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

 1 >>> def lazy_sum(*args):
 2 ...     def sum():
 3 ...         ax = 0
 4 ...         for n in args:
 5 ...             ax = ax + n
 6 ...         return ax
 7 ...     return sum
 8 ...
 9 >>> f = lazy_sum(1, 3, 5, 7, 9)
10 >>> f
11 <function lazy_sum.<locals>.sum at 0x1014ae730>
12 >>> f()
13 25

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

1 >>> f1 = lazy_sum(1, 3, 5, 7)
2 >>> f2 = lazy_sum(1, 3, 5, 7)
3 >>> f1
4 <function lazy_sum.<locals>.sum at 0x1014ae8c8>
5 >>> f2
6 <function lazy_sum.<locals>.sum at 0x1014ae7b8>
7 >>> f1 == f2
8 False

二、闭包

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

简单的说,这种内部函数可以使用外部函数变量的行为,就叫闭包。

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

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

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

 1 >>> def count():
 2 ...     fs = []
 3 ...     for i in range(1, 4):
 4 ...         def f():
 5 ...             return i * i
 6 ...         fs.append(f)
 7 ...     return fs
 8 ...
 9 >>> f1, f2, f3 = count()
10 >>> f1()
11 9
12 >>> f2()
13 9
14 >>> f3()
15 9

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

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

 1 >>> def count():
 2 ...     def f(j):
 3 ...         def g():
 4 ...             return j * j
 5 ...         return g
 6 ...     fs = []
 7 ...     for i in range(1, 4):
 8 ...         fs.append(f(i))
 9 ...     return fs
10 ...
11 >>> f1, f2, f3 = count()
12 >>> f1()
13 1
14 >>> f2()
15 4
16 >>> f3()
17 9
时间: 2024-10-11 07:51:03

python 闭包 Closure 函数作为返回值的相关文章

Python学习笔记之函数作为返回值、闭包的解释

函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: 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:

Python的函数式编程-传入函数、排序算法、函数作为返回值、匿名函数、偏函数、装饰器

函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计的基本单元. 传入函数 函数的本身也可以作为参数. Python内建的mapreduce的函数.(来源于谷歌的,后来被道格这家伙开源了,成为当今处理大数据最火热的hadoop中的计算模型---MapReduce) 我们先看map.map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序

函数定义,返回值,传参,命名空间,闭包

函数的返回值: return是返回给函数的调用者 函数外面的代码想要获取函数的执行结果,就可以在函数里,用return语句把结果返回. 注意:在函数的执行过程中主要遇到return语句,就会停止执行并返回结果, so可以理解为return语句代表着函数的结束 如果未在函数中指定return,那这个函数的返回值为none 函数的返回值,可以返回一个函数名(可以将嵌套函数里的执行结果return给函数体外,进行执行) return永远且只能返回一个值,,如果返回多各值呢? def func1(nam

Python函数之返回值、作用域和局部变量

一.函数返回值 说到返回值,相信大家肯定都认识,没错,就是return. 所谓返回值可以这样理解:函数外部的代码要想获取函数的执行结果,就可以在函数里用return语句把结果返回. 那具体怎么用呢?接着往下看: #!/usr/bin/env python3 #-*- coding:utf-8 -*- # write by congcong # return 表示一个程序的结束,他可以返回任意的元素,列表或字典 def stu_info(name,age,course): print(name,a

Python全栈__函数的初识、函数的返回值、函数的参数

1.函数的初识 def关键字 空格 函数名(与变量名命名规则相同):英文冒号 函数体 执行函数:函数名+() 函数是以功能为导向的. def login(): pass def register(): pass 1 def my_len(): 2 l1 = [1, 2, 3, 1, 6, 9, 10] 3 count = 0 4 for i in l1: 5 count += 1 6 my_len() 2.函数的返回值 return: 1.函数中遇到 return 结束函数,下面代码不执行. d

(一)Python入门-5函数:02形参和实参-文档字符串-函数注释-返回值详解

一:形参和实参 [操作]定义一个函数,实现两个数的比较,并返回较大的值. 1 def printMax(a,b): 2 '''实现两个数的比较,并返回最大值!''' 3 if a >b: 4 print(a,'较大值') 5 else: 6 print(b, '较大值') 7 8 printMax(20,30) 9 printMax(30,5) 10 11 #测试文档字符串的使用 12 help(printMax) 13 help(printMax.__doc__) 上面的 printMax 函

python基础 带参数以及返回值的函数装饰器

1 #带参数以及返回值的函数装饰器,上一篇博客记录了无参数函数装饰器写法以及使用方案,当函数有参数以及返回值时需要将装饰器进行如下修稿 2 def timer(fun): 3 def deco(*args,**kwargs): #被装饰函数实际是执行deco,所以在此将被装饰函数参数进行传递 4 start_time = time.time() 5 res = fun(*args,**kwargs) #将被装饰函数的返回值接收 6 stop_time = time.time() 7 return

python 闭包(closure)

闭包的定义: 闭包就是一个函数,这个函数可以记住封闭作用域里的值,而不管封闭作用域是否还在内存中. 来一个例子: def happy_add(a): print 'id(a): %x' % id(a) def do_add(b): return a + b print 'id(do_add): %x' % id(do_add) return do_add test_one = happy_add(1) test_one(9) print repr(test_one) print '\n-----

Scheme高阶函数之函数作为返回值暨currying/柯里化

1.4.1currying/柯里化 通常,编程的函数可以有一个参数列表,而λ表达式要求单参数.所以,currying/柯里化--多个参数的函数转化为只有一个参数的多个函数的连续调用,需要函数作为返回值. 有λ表达式,λx. λy. ( 2x+3y) (define (F x y)(+ ( * 2 x) (* 3 y)));;;等价于下面的表示 (define F (lambda ( x y) (+ ( * 2 x) (* 3 y)) ) ) (F 2 3)            → 13 函数F