Python 之 返回函数

函数作为返回值

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。在以前的学习中,我们可能看见的求和函数都是像下面这样的:

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

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

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

>>> answer = calcu(1,2,4,6,7)
>>> answer
<function calcu.<locals>.sum at 0x0000022572CBC1E0>

我们可以看出当我们调用最大的calcu方法时,返回的是函数sum,而当我们再去调用sum函数时,返回的才是求得的和:

>>> answer()
20

在这个例子中,我们在函数calcu中又定义了函数sum,并且,内部函数sum可以引用外部函数calcu的参数和局部变量,当calcu返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为闭包的程序结构拥有极大的威力。
而且当我们调用calcu方法时,每次调用都会返回一个新的函数,即使传入相同的参数:

>>> f = calcu(1,3,5,7,9)
>>> f
<function calcu.<locals>.sum at 0x000002257366C048>
>>> g = calcu(1,3,5,7,9)
>>> g
<function calcu.<locals>.sum at 0x000002257366C0D0>
>>> f == g
False

f 和 g 的调用互不影响。

闭包

注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。
另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。我们来看一个例子:

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

你可能以为这段代码的结果是1,4,9,但是事实是这样的:

>>> f1,f2,f3 = count()
>>> f1()
9
>>> f2()
9
>>> f3()
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

利用闭包返回一个计数器函数,每次调用它返回递增整数:

def createCounter():
	s = [0]
	def counter():
		s[0] = s[0]+1
		return s[0]
	return counter
发布了37 篇原创文章 · 获赞 42 · 访问量 4503

猜你喜欢

转载自blog.csdn.net/qq_43337175/article/details/104427672