一.python闭包
1.定义
闭包,又称闭包函数或者闭合函数,其实和前面讲的嵌套函数类似,不同之处在于,闭包中外部函数返回的
不是一个具体的值,而是一个函数。一般情况下,返回的函数会赋值给一个变量,这个变量可以在后面被继
续执行调用。
例如,计算一个数的n次幂,用闭包可以写成下面的代码
#闭包函数,其中 exponent 称为自由变量,意为指数
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
8
在上面,外部函数nth_power()的返回值是函数exponent_of(),而不是一个具体的数值。
需要注意的是,在执行完 square = nth_power(2) 和 cube = nth_power(3) 后,外部函数
nth_power() 的参数 exponent 会和内部函数 exponent_of 一起赋值给 squre 和 cube,
这样在之后调用 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)
很显然,第二种表达方式更为简洁易读,每次都可以少输参数
其次,和缩减嵌套函数的优点类似,函数开头需要做一些额外工作,当需要多次调用该函数时,如果将那些
额外工作的代码放在外部函数,就可以减少多次调用导致的不必要开销,提高程序的运行效率。
2.Python闭包的_closure_属性
闭包比普通函数多了所谓_closure_属性,该属性记录着自由变量的地址。当闭包被调用时,系统就会根据该地址找到对应的自由变量,完成整体的函数调用
以 nth_power() 为例,当其被调用时,可以通过 __closure__ 属性获取自由变量(也就是程序中的 exponent 参数)存储的地址,例如
---------------------------------------------
def nth_power(exponent):
def exponent_of(base):
return base ** exponent
return exponent_of
square = nth_power(2)
#查看 __closure__ 的值
print(square.__closure__)
输出结果为
(<cell at 0x0000014454DFA948: int object at 0x00000000513CC6D0>,)
可以看到,显示的内容是一个 int 整数类型,这就是 square 中自由变量 exponent 的初始值。
还可以看到,__closure__ 属性的类型是一个元组,这表明闭包可以支持多个自由变量的形式。
二.lambda表达式(匿名函数)
lambda 表达式,又称匿名函数,常用来表示内部仅包含 1 行表达式的函数。如果一个函数的函数体
仅有1行表达式,则该函数就可以用 lambda 表达式来代替。
语法格式如下:
name = lambda [list] : 表达式
其中,定义 lambda 表达式,必须使用 lambda 关键字;[list] 作为可选参数,等同于定义函数是指定的参数列表;value 为该表达式的名称。
转换为普通函数
def name(list):
return 表达式
name(list)
倘若我们设计一个计算两数之和的函数,普通函数如下
def add(x, y):
return x+ y
print(add(3,4))
又因为上面的函数仅有一行表达式,因此可用lambda表达式
add = lambda x,y:x+y
print(add(3,4))
可以这样理解 lambda 表达式,其就是简单函数(函数体仅是单行的表达式)的简写版本。相比函数,
lamba 表达式具有以下 2 个优势:
对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁;
对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能。(很重要)