python有参装饰器与多层语法糖

一、有参装饰器

 
# 区别于无参装饰器,有参装饰器,顾名思义,就是装饰器带有参数,首先我们来看无参装饰器


# 无参装饰器模板如下:

# def outter(func):
#     def inner(*args, **kwargs):
#         '''函数调用前需要增加的功能'''
#         res = func(*args, **kwargs)
#         '''函数调用后需要增加的功能'''
#         return res
# 
#     return inner
# 
# 
# def index(*args, **kwargs):
#     print(*args, **kwargs)
#     return '任巍峰大帅哥'


# 此时,两层函数的形参都有着自己特定的功能,func用来接收函数名,(*args,**kwargs)用来接收被装饰函数的参数,那么如果装饰器中如果需要参数,怎么办
# 那么我们或许会说,我们只需要在outter(func,a,b,c),或者inner(a,b,c,*args,**kwargs)装饰器需要几个参数,我们传几个参数就行
# 是的,如果作为一个函数,我们嵌套的时候可以这样子做,但是作为一个装饰器,我们应该遵循函数装饰前后调用方式不变的原则,所以,我们将外层函数的返回值设置成内层函数的函数名,
# 首先我们看一下无参装饰器是怎么实现调用方式不变得

# index = outter(index)  #先调用outter函数,并将该函数的值赋予变量名index
# index(1, 2)            #index()>>>>>等价于outter函数返回值()>>>>等价于inner()

# 方式一:如果我们采用(a,b,c,*args,**kwargs)这种方式为装饰器传参,那么我们在调用的时候,就必须采用
# index(a,b,c,*args,**kwargs)>>>>inner(a,b,c,*args,**kwargs),这与原来的调用方式明显不一样
# 作为装饰器,被装饰函数装饰前怎么调,装时候还是应该怎么调,所以排除方式一

#方式二:那么,如果是outter(func,a,b,c),这种呢,这种如果单纯的作为嵌套函数是可以的,但是,作为装饰器,我们是需要用的
# 我们总不能每次用之前加一行代码 index = outter(index,a,b,c) 吧,所以,我们用的是语法糖,@outter,而语法糖默认传的参数就index一个
# 综上所述,既然通过形参无法满足内部函数对参数的需求,那么就采用第二种传参方式,闭包,在函数外面在包一层函数,有参装饰器呼之欲出
# # 
# def auth(a,b,c):
#     def outter(func):
#         def inner(*args, **kwargs):
#             '''函数调用前需要增加的功能'''
#             res = func(*args, **kwargs)
#             '''函数调用后需要增加的功能'''
#             return res
#     
#         return inner
#     return outter

# 至此,有参装饰器模板补充完整,以后内部需要多少个参数,都可以通过auth(a,b,c)的形参传入,故而,装饰器最多只有三层
# 那么调用的时候如何做到调用方式不变呢,首先看语法糖在无参的时候怎么操作

# @outter   >>>>>>>>,这里,@outter,他内部的函数是默认将下边函数的名字当作参数传入outter函数,即>>>>index = outter(index)
# def index(*args, **kwargs):
#     print(*args, **kwargs)
#     return '任巍峰大帅哥'


# 那么,对于有参装饰器,我们只需要在他前边加一行代码:outer = auth(a,b,c)>>>>等价于outter函数
# 此处,有人会问,outter等价于函数outter函数不是多此一举吗,这是因为,outter函数是局部空间的,你在全局作用域中直接找outter是无法找到的,因此不是多次一举.
# 综上所述,我直接在全局作用域给函数添加装饰器,@outter是不是就可以合并成一步,@auth(a,b,c),
# 综上所述,有参函数模板如下
#  def auth(a,b,c):
#     def outter(func):
#         def inner(*args, **kwargs):
#             '''函数调用前需要增加的功能'''
#             res = func(*args, **kwargs)
#             '''函数调用后需要增加的功能'''
#             return res
#     
#         return inner
#     return outter
# 调用方式如下

# @auth(a,b,c)
# def index(*args, **kwargs):
#     print(*args, **kwargs)
#     return '任巍峰大帅哥'


# index()

二、多层语法糖

理解了有参装饰器,那么多层语法糖的理解就显得顺理成章,多层语法糖的语法赋值是从下而上的,内层小函数执行时是从上而下的,我们通过一个例题来理解:判断七句print执行顺序

def outter1(func1):
    print('加载了outter1')

    def wrapper1(*args, **kwargs):
        print('执行了wrapper1')
        res1 = func1(*args, **kwargs)
        return res1

    return wrapper1


def outter2(func2):
    print('加载了outter2')

    def wrapper2(*args, **kwargs):
        print('执行了wrapper2')
        res2 = func2(*args, **kwargs)
        return res2

    return wrapper2


def outter3(func3):
    print('加载了outter3')

    def wrapper3(*args, **kwargs):
        print('执行了wrapper3')
        res3 = func3(*args, **kwargs)
        return res3

    return wrapper3


@outter1
@outter2
@outter3
def index():
    print('from index')


index()

运行结果如下

加载了outter3
加载了outter2
加载了outter1
执行了wrapper1
执行了wrapper2
执行了wrapper3
from index

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值