一.闭包
如果一个内嵌函数中引用了外部函数中的变量(非全局变量)。那么该内嵌函数称之为闭包
也就是将组成函数的语句和这些语句的执行环境打包在一起时,得到的对象
闭包满足的三个条件:
1.必须是内嵌函数
2.外层函数返回值是内嵌函数
3.内嵌函数引用外层函数变量
def Funx(x):
def Funy(y):
return x*y
def Funz(z):
return x*z
return Funy,Funz
y,z=Funx(5) #接收两个内嵌函数
print(y(2),z(3)) #分别调用
闭包:Python解析变量的LEGB法则,Local>Enclosing>Global>Bulitin ,在任何一层找到以后结束查找
Local 代表本地变量即内嵌函数内变量,
Enclosing 代表外层函数变量,如果是嵌套外层,则由内向外一直查找
Global 全局变量,即查找当前模块的变量
Bulitin 内置模块的预定义变量中查找
下面来一个例子帮助了解:
#foo.py
filename="foo.py"
def call_func(f):
return f()
import foo #导入foo.py模块
filename="func.py"
def show_name():
print(filename)
call_func(show_name) #输出func.py
原因:由于闭包是封存上下文环境,所以call_func(show_name)会使用内嵌函数show_name的上下文
用LEGB法则解释:show_name函数和其外部里没有filename变量,就去当前模块func.py中查找该变量
二.装饰器&语法糖
装饰器是闭包的应用,在不修改原函数代码的情况下,对函数包装,为函数添加功能
def gd(fun):
def wrapper():
return fun()+'我吃火锅,你吃火锅底料\t'
return wrapper
def kt(fun):
def wrapper():
return fun()+'我吹空调,你吹空调外机\t'
return wrapper
@gd
@kt
def test():
return '我吃冰棍,你吃冰棍棒棒\t' # 相当于gd(kt(test)())
print(test())
总结:闭包是典型的惰性赋值,外层函数局部变量不会丢失,会被封装到内嵌函数的环境中