概念
闭包和嵌套函数类似,不同的是,这里外部函数返回的是一个函数,而不是一个具体的值。返回的函数通常赋予一个变量,这个变量可以在后面被继续执行调用。
实例
Talk is cheap, show me the code. 比如,我们想计算一个数的 n 次幂,用闭包可以写成下面的代码:
def nth_power(exponent):
def exponent_of(base):
return base ** exponent
return exponent_of # 返回值是exponent_of函数
square = nth_power(2) # 计算一个数的平方
cube = nth_power(3) # 计算一个数的立方
print(square(2)) # 计算2的平方
print(cube(2)) # 计算2的立方
# 输出
4 # 2^2
8 # 2^3
这里外部函数 nth_power() 返回值,是函数 exponent_of(),而不是一个具体的数值。需要注意的是,在执行完square = nth_power(2)和cube = nth_power(3)后,外部函数 nth_power() 的参数 exponent 仍然会被内部函数 exponent_of() 记住。这样,之后我们调用 square(2) 或者 cube(2) 时,程序就能顺利地输出结果,而不会报错说参数exponent 没有定义了。
看到这里,你也许会撕开,为什么要闭包呢?上面的程序,我也可以写成下面的形式啊!
def nth_power_rewrite(base, exponent):
return base ** exponent
确实可以,不过,要知道,使用闭包的一个原因,是让程序变得更简洁易读。设想以下,比如你许哟啊计算很多个数的平方,那么你觉得写成下面哪一种形式更好呢?
# 不适用闭包
res1 = nth_power_rewrite(base1, 2)
res2 = nth_power_rewrite(base2, 2)
res3 = nth_power_rewrite(base3, 2)
...
# 使用闭包
square = nth_power(2)
res1 = square(base1)
res2 = square(base2)
res3 = square(base3)
...
显然是第二种。首先直观来看,第二种形式,让你每次调用函数都可以少输入一个参数,表达更为简洁。
其次,当函数开头需要做一些额外工作,而你有需要多次调用这个函数时,将那些额外工作的代码放在外部函数,就可以减少多次调用导致的不必要的开销,提高程序的运行效率。
另外还有一点,我们有机会在讲,闭包常常和装饰器(decortor)一起使用。
禅定时刻
合理地使用闭包,则可以简化程序的复杂度,提高可读性。
See you!