python中的装饰器(以及多个装饰器详细执行过程)

装饰器

1.如果要增强一个函数的功能,但又不希望更改原函数中的代码,这种在代码运行期间动态增加功能的机制被称为装饰器

  【Decorator】

2. 本质:实际上就是一个闭包,只不过被装饰的函数需要作为参数传递给闭包

3.装饰器的书写格式:给闭包的外部函数设置一个参数【需要被装饰的函数】,

  外部函数的返回值是内部函数的引用【装饰的结果】,这种函数被称为高阶函数

4.装饰器的好处:

    ① 不用修改源代码就可以更改函数

    ② 提高代码的维护性

    ③ 提高代码的复用性

5.应用场景:

    ① 引入日志

    ② 统计函数的执行时间 

    ③权限校验

    ④缓存

 

 装饰器的使用

1. 简单的装饰器

# 1. 简单的装饰器
def test():
    print("人生苦短,我用python")


# 装饰器的书写步骤
# 1.书写闭包
# 2.传参:给outter设置参数,该参数表示需要被增加的功能函数
def outter(func):
    def inner():
        # 3.调用原函数
        func()
        # 4.增加新功能
        print("PYTHON")

    # 5.将装饰之后的结果返回【方便在函数外面调用】
    return inner


# 6.然后进行调用
f = outter(test)
f()

"""
装饰器的执行顺序:
    1.f = outter(test),调用outter函数,func = test , f = inner
    2.f(),调用inner函数
    3.func(), 调用test原函数
"""

2.有参数的装饰器

# 2.有参数的装饰器

def getAge(age):
    print(age)


# 需求:当传入的年龄为负数时,打印相反数
def outter2(func):
    def inner2(num):
        if num < 0:
            num = abs(num)
        func(num)

    return inner2


f2 = outter2(getAge)  # func = getAge   f2 = inner2
f2(-31)
"""
通过上述的操作,将边界检查的操作隔离到单独的函数中,并没有修改原函数
 给装饰器的内部函数是否需要设置参数,如果原函数有参数,并且在装饰器中
 的inner中需要对原函数的参数运算
 则建议给inner设置参数,该参数需要和原函数的参数有关
"""

3.使用符号@将装饰器应用于函数         

   @的作用:简化装饰器的调用          @装饰器名称    应用于被装饰的函数声明的前面

     # 注意:使用@使用装饰器,则装饰器必须先存在,然后才能使用它,即就是要先有装饰器函数

   使用@应用装饰器,则调用装饰器只需要通过原函数名调用

# 3.使用符号@将装饰器应用于函数          @的作用:简化装饰器的调用
def outter3(func):
    def inner3(num):
        if num < 0:
            num = abs(num)
        func(num)

    return inner3

# 使用@应用装饰器
@outter3
def getAge(age):
    print(age)


# 调用
getAge(-69)

"""
@装饰器的执行的顺序
    1.@outter3: 相当于f = outter3(getAge),完成了func = getAge,
                f = inner3也就是getAge = inner3
    2.getAge(-69) : 相当于【f(-69)】,调用inner3
"""

4.一个装饰器修改多个函数

   ①多个函数都没有参数


def outter4(func):
    def inner4():
        func()
        print("装饰器中的新功能")

    return inner4


@outter4
def show1():
    print("show-1")


@outter4
def show2():
    print("show-2")


@outter4
def show3():
    print("show-3")


show1()
show2()
show3()

 运行结果:

 ②多个函数拥有不同的参数

def outter4(func):
    def inner4(*args, **kwargs):  # 使用不定长参数
        func(*args, **kwargs)
        print("装饰器中的新功能")

    return inner4


@outter4
def show1():
    print("show-1")
    print("show1无参数")


@outter4
def show2(a, b):
    print("show-2")
    print('show2中的参数:', a, b)


@outter4
def show3(num1, num2, num3):
    print("show-3")
    print('show3中的参数:', num1, num2, num3)


show1()
show2(2, 3)
show3(4, 5, 6)

 打印结果:

5.多个装饰器修改一个函数

    给同一个函数同时增加了多个新的功能

def outter_1(func1):
    def inner_1(*args, **kwargs):  # 使用不定长参数
        print("inner_1内容")
        func1(*args, **kwargs)
        print("第一个装饰器-----1")

    return inner_1


def outter_2(func2):
    def inner_2(*args, **kwargs):  # 使用不定长参数
        print("inner_2内容")
        func2(*args, **kwargs)
        print("第二个装饰器-----2")

    return inner_2


def outter_3(func3):
    def inner_3(*args, **kwargs):  # 使用不定长参数
        print("inner_3内容")
        func3(*args, **kwargs)
        print("第三个装饰器-----3")

    return inner_3


@outter_1
@outter_2
@outter_3
def show_1():
    print("show_1")


show_1()
"""
    多个装饰器加载的顺序
    1.@outter_3:show_1原函数-->outter_3-->func3 = show_1原函数-->show_1指向了inner_3
    2.@outter_2:inner_3-->outter_2-->func2 = inner_3-->show_1指向了inner_2
    3.@outter_1: inner_2-->outter_1-->func1 = inner_2-->show_1最终指向了inner_1
    所以多个装饰器的执行调用过程
    show_1()-->inner_1()-->func1()-->inner_2()-->func2()-->inner_3()-->func3()-->show_1()原
"""

 运行过程:

 

"""
结论:
    如果多个装饰器修饰同一个函数,
            传参:       从下往上【就近原则】
    代码的执行顺序:       从上往下
"""

 

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python,如果一个函数使用了多个装饰器,那么它们的执行顺序是从下往上的。也就是说,最下面的装饰器最先执行,最上面的装饰器最后执行函数执行完后,装饰器执行顺序则与装饰器定义的顺序相反。 例如,下面是一个使用三个装饰器的示例: ``` python def decorator1(func): def wrapper(*args, **kwargs): print("Decorator 1 before function execution") func(*args, **kwargs) print("Decorator 1 after function execution") return wrapper def decorator2(func): def wrapper(*args, **kwargs): print("Decorator 2 before function execution") func(*args, **kwargs) print("Decorator 2 after function execution") return wrapper def decorator3(func): def wrapper(*args, **kwargs): print("Decorator 3 before function execution") func(*args, **kwargs) print("Decorator 3 after function execution") return wrapper @decorator1 @decorator2 @decorator3 def my_function(): print("Function execution") my_function() ``` 输出结果为: ``` Decorator 3 before function execution Decorator 2 before function execution Decorator 1 before function execution Function execution Decorator 1 after function execution Decorator 2 after function execution Decorator 3 after function execution ``` 可以看到,装饰器3最先执行,然后是装饰器2,最后是装饰器1。而函数执行完后,装饰器执行顺序则与装饰器定义的顺序相反,即装饰器1最先执行,然后是装饰器2,最后是装饰器3。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还是那个同伟伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值