python中,函数在执行时才搜索需要的变量,而函数在被引用时只相当于起了个别名,而不执行任何语句
闭包closure
闭包,是指【携带完整上下文环境】的一种函数:
它被嵌套在【外层函数】的内部,并且引用了【外层函数】中的enclosing变量
一句话,闭包就是能够读取其他函数内部变量的函数
拿例子理解
def f1(a):
# 接收E-Enclosing变量a
def f2(b):
# 接收L-Local变量b
# f2引用了外层函数f1的Enclosing变量a来完成a+b
return a + b
return f2
# 调用f1(),实现了f=f2。这时虽然f1()已经调用结束,但是a=1已经绑定在f2中,而不会随着外层函数f1()调用结束而消失
# 绑定了a=1的f2再被f引用
f = f1(1)
print(f(3))
----
4
在这个例子中,函数f2是一个内层函数。对于内层函数f2而言,无论是自身的local变量b还是外层嵌套函数的enclosing变量a,凡是被需要的一切变量都会被保留,而不随着外层嵌套函数的调用结束而消失。可以理解为,内层函数执行时所需的一切上下文环境被保留了下来,这样的函数称为闭包
闭包的几个tips
-
1.闭包应该对上下文环境只读不写,不可改变外函数enclosing变量名指向的内存地址
划重点——闭包就是被设计用来携带特定上下文环境的一种函数,它区别于普通函数的特殊之处就是实现了对上下文环境的保存。从这个角度看,闭包要做的,是对环境的保存,而不是修改。也就是说,闭包应该对上下文环境只读不写。但这里的不写并没有特别严格,不写指的是不改变enclosing变量的内存地址,对于可变对象来说(如enclosing作用域的list对象),修改值并不改变内存地址,因此enclosing作用域的可变对象还是能够修改值的
当然,如果非要在闭包中修改外函数中enclosing不可变对象的值(如int型),也可以,需要使用 nonlocal 关键字声明一下
-
2.一个闭包在不同的环境下得到不同的结果
通过修改外部作用域的局部变量——也就是给闭包安排不同的上下文环境,从而得到不同的结果。【这就是python的装饰器】
-
3.闭包减少了全局变量的使用,将需要的变量限定在enclosing和local作用域;同时也对数据进行了隐藏
另外,关于闭包,还可参阅https://www.programiz.com/python-programming/closure