从零开始学Python-Day29-返回函数

Python零基础 木人张 3年前 (2020-04-01) 851次浏览 0个评论 扫描二维码
文章目录[隐藏]

返回函数顾名思义就是将函数作为返回值返回。一般情况下的求和函数是这样事儿的:

>>> 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

木人张,版权所有丨如未注明 , 均为原创,禁止转载。
喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址