返回函数顾名思义就是将函数作为返回值返回。一般情况下的求和函数是这样事儿的:
>>> def calc_sum(*args):
ax = 0
for n in args:
ax = ax +n
return ax
>>> calc_sum(1,2,3,4,5)
15
但是有些情况下,我们不希望程序立即计算求和,而是需要时再计算,可以让函数不返回结果,而是返回一个函数:
>>> def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
>>> f = lazy_sum(1,2,3,4,5)
>>> f
.sum at 0x10d696280>
>>> f()
15
可以看到,直接调用lazy_sum时,并没有进行计算,而是返回了一个sum函数,只有调用f()时,才会计算真正的结果。我们知道这里在lazy_sum中定义了一个sum函数,sum函数成为内部函数,lazy_sum成为外部函数,内部函数可以引用外部函数的参数和变量,而当外部函数lazy_sum返回sum时,相关的参数和变量都保存到了返回的函数中,这种程序称之为闭包(“Closure”)。值得注意的一点,调用lazy_sum时,每次调用返回的都是一个全新的函数,即使传入参数一致:
>>> f1 = lazy_sum(1,2,3,4,5)
>>> f2 = lazy_sum(1,2,3,4,5)
>>> f1 == f2
False
关于闭包
上面的例子中返回的函数在内部引用了局部变量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
为什么f1,f2,f3没有按我们预想的一样输出1,4,9呢?因为返回的函数引用了变量i,在for循环结束时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
下面,利用闭包返回一个计数器函数,每次调用它返回递增整数:
>>> def createcounter():
n = 0 # 先定义一个变量作为初始值
def counter(): # 定义一个内部函数用来计数
nonlocal n # 声明变量n非内部函数的局部变量,否则内部函数只能引用,一旦修改会视其为局部变量,报错“局部变量在赋值之前被引用”
n += 1 # 每调用一次内部函数,对n + 1
return n # 返回n的值
return counter
>>> counterA = createcounter()
>>> print(counterA(), counterA(), counterA(), counterA(), counterA())
1 2 3 4 5
4000520066 欢迎批评指正
All Rights Reserved 新浪公司 版权所有