嵌套函数中,内部函数引用外部函数的参数和变量所获得的结果,被外层函数当做返回值给返回的情况称为闭包函数。
下面先来看看一段代码,然后再详细解释闭包函数的原理。
def func(m):
n = 5
def func1(x):
print(m + n + x) # 使用外部函数的变量和参数来运算
return func1 # 返回内部函数
test = func(3) # func(3)的返回值就是func1,所以test=func1()
test(10) # 这时候相当于调用函数func1并且传参
返回结果:
<function func.<locals>.func1 at 0x00000000023A13A0>
18
上面的外层函数func接收一个参数m,内部定义一个变量n和一个函数func1,在func1中需要接收一个参数x。当我们执行func(3)的时候返回一个func1函数,当我们再调用test这个变量的时候,其实就是调用外层函数返回的内部函数func1,所以也能传参,这时候就有了结果。
下面我们把之前的学生上网案例拿出来,使用闭包函数来选择内部函数返回不同功能作用的结果,类似于返回函数,但是本质有区别,返回函数是对返回的函数种类进行筛选,闭包函数是对内部函数处理的不同结果进行返回。
age = input('请输入你的年龄:')
aa = '学生'
bb = '成年人'
def func(aa, bb):
# 定义其他内部函数
def func1(n):
if n >= 18:
print('你是大%s,属于%s,可以上网了' % (aa, bb))
else:
print('你是小%s,属于未%s,不可以上网了' % (aa, bb))
return func1
test = func(aa, bb) # 先把参数传递进去给内部函数使用
test(int(age)) # 对内部函数返回的结果进行筛选
这里要注意闭包函数内部函数如果定义和外部函数同名变量时的作用域问题。
def test1():
m = 100
def test2():
nonlocal m # 如果想改变外部变量值一定要用nonlocal,否则被视为重新定义的局部变量
m = 101
print(m)
print(m)
test2()
print(m) # 这里的m变成101了
return test2
注意:闭包函数内的代码执行顺序
def test3():
m = 100
def test4():
print(m) # 这里没有m3的变量
m = 200
print(m) # 返回结果为200
return test4
test = test3() # test() # 这里注释以后不报错,说明没有执行内部函数,也就是m被重新赋值后,调用函数以后