将函数作为返回值返回,也是一种高阶函数。
这种高阶函数我们也称为闭包,通过闭包可以创建一些只有当前函数能访问的变量
可以将一些私有的数据藏到闭包里。
这里我联想到多用户电脑,当打开一台电脑,有多个用户时,选择自己的,就会将自己之前使用过和设置过的自己的信息显示给自己。在外部空间,如果没有进入用户名是我自己的话,是查询不到自己的一些信息的。
def fn():
a = 10
# 在函数内部再定义一个函数
def inner_func():
print('我是inner_func!')
if a:
print('我可以查询到fn函数中的变量a:', a)
else:
print('我查询不到fn函数中的变量a!')
return inner_func
#
r = fn()
print(r)
# <function fn.<locals>.inner_func at 0x10048d4c0>
r()
# 我是inner_func!
# 我可以查询到fn函数中的变量a: 10
if a:
print('在全局环境中,我可以查询到fn函数中的变量a:', a)
else:
print('在全局环境中,我查询不到fn函数中的变量a!')
# 这个时候会抛出异常:NameError: name 'a' is not defined
# 所以在全局环境中,查询不到fn函数中的变量 a
闭包举例:
# 制作一个求解平均值的函数
def make_average():
# 创建一个列表,用来保存数值
nums = []
# 创建一个内部函数,用来计算平均值
def average(n):
nums.append(n)
return sum(nums)/len(nums)
return average
num_average = make_average()
print(num_average(10))
print(num_average(4))
print(num_average(1))
print(nums)
# 10.0
# 7.0
# 5.0
# NameError: name 'nums' is not defined
# 这样变量 nums 就不会被修改或者删除操作了,也就避免了该程序的异常。
# 如果没有最外层的 make_average 函数,如下所示:
# 创建一个列表,用来保存数值
nums = []
# 创建一个内部函数,用来计算平均值
def average(n):
nums.append(n)
return sum(nums)/len(nums)
print(average(10))
print(average(4))
# 10.0
# 7.0
# 这个时候仿佛一切正常,但是···
# 如果有人修改了变量 nums ,
nums.append(100)
print(average(1))
# 28.75
# 这个背景下,我们不希望有人可以修改变量 nums
# 所以,就可以使用闭包,将变量 nums 放到函数内部
-
形成闭包的要件:
- 函数嵌套
- 将内部函数作为返回值返回
- 内部函数必须要使用到外部函数的变量