Python闭包与装饰器

时间:2023-01-16 22:47:54

一.闭包

如果一个内嵌函数中引用了外部函数中的变量(非全局变量)。那么该内嵌函数称之为闭包

也就是将组成函数的语句和这些语句的执行环境打包在一起时,得到的对象

闭包满足的三个条件:

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())
总结:闭包是典型的惰性赋值,外层函数局部变量不会丢失,会被封装到内嵌函数的环境中