一 闭包

1定义

如果有一个外部函数Foutter,一个内部函数Finner,Finner使用了Foutter的变量,Foutter返回了Finner的函数名,则这个内部函数Finner被称为闭包

def Foutter():
    a=5
    def Finner():
        print(a)
    return  Finner  #注意返回的是函数名,不是B的返回值  打印结果为Finner的地址

2调用

def Fa():
    a=5
    def FB():
        print(a)
    return  FB

#调用方式1
Fa()() #调用内函数

#调用方式2
innerF= Fa() #先存一下内函数
innerF()

3 如果外函数有参数,闭包会保留外函数的参数的值,即使是临时变量

def Fa(p1):
    p2=5
    def FB(p3):
        print(p1+p2+p3)
    return  FB

innerF= Fa(10)
innerF(20)#输出35

二 装饰器

装饰器是一种闭包
特点是外部函数的其中一个参数是函数,且这个函数被闭包函数调用,则这个闭包就是装饰器
可以在其他函数不做更改的情况下,直接添加新功能

定义

#send(msg)是被装饰的函数
def send(msg):#被装饰函数可以有参数也可以有返回值
    print("发送消息"+msg)

def outer(fn):#外部函数的参数数量不限制
    def inner(msg):#inner这个闭包被称为装饰器
        print("登录")
        fn(msg)#可以简单调用,也可以return fun
    return inner

outer(send)("我的参数")

实际使用

def outer(fn):#外层函数只能有一个参数用来接收被装饰方法
    def inner(msg):#装饰器如果有参数,则被装饰函数也必须有一样的参数,否则会报错
        print("登录")
        fn(msg)
    return inner

@outer#装饰器语法糖,此时send已经等价于 outer(send)
def send(msg):
    print("发送消息"+msg)

send("我的参数")#调用被装饰的方法

闭包穿透传参
对于可变参数和关键字参数,传参时需要注意带着*号

def outer(fn):#定义装饰器
    def inner(*args, **kwargs):
        print("登录")
        fn(*args,**kwargs)#注意这里不能是fn(arg,kwargs),如果这样做相当于把args这个元组和kwwargs这个字典当作fun的args参数传给被装饰函数
    return inner

def send(*args, **kwargs):
    print(args)
    print(kwargs)

outer(send)(name="wuiz");

输出:
登录
()
{'name': 'wuiz'}

多个装饰器

@装饰器1
@装饰器2  #先执行装饰器2,离方法最近的装饰器先执行
def Fun():
	print("11")

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐