乐趣区

关于Python之路:Python之路day14装饰器多层装饰器

前言时刻

明天学习了装璜器的用法,很早之前就学习过……

来来总结一波:

明天次要就学习了装璜器的作用以及用法

装璜器很重要,倡议弄懂。

1、装璜器概念

装璜器顾名思义就是对一个函数装璜一下扩大一个性能,而不扭转其函数外部的代码,去掉装璜器不影响原函数的性能,加上就可扩大一个性能。例如:能够把装璜器比作化妆品,化妆品能够使人脸的变得更加难看,然而擦掉化妆品,脸还是脸。只是应用化妆品装璜了下你的脸变得难看了,丝毫没有扭转脸的属性。

有人说装璜器有啥用呢?装璜器完满的合乎了代码凋谢关闭准则。

什么是代码凋谢关闭准则?

  1. 封闭性:对批改是关闭的,扩大的代码状况下,不能批改原函数的代码
  2. 开放性:容许对曾经设计好的代码进行扩大性能。

试想一个场景,明天过节气,老板让你给网站扩大一个充 1 送一流动性能,你的做法是硬扩、软扩、还是智扩?听我细细道来

def charge_money(pay_sum):
    
    print(f"充值到账:{pay_sum} 元")
    
    return True

# 1、做流动之前
charge_money(666)
# 曾经充值了:666 元

1)硬扩:

def charge_money(pay_sum):
    
    print(f"流动赠送了:{pay_sum} 元")
    pay_sum = pay_sum * 2
    
    print(f"充值到账:{pay_sum} 元")
    
    return True


# 2、做流动 硬扩
charge_money(666)

# 流动赠送了:666 元
# 充值到账:1332 元

这里有个问题,那就是更改了原函数的内容,不合乎封闭性准则。

2)软扩:

# 3、软扩


def salse_activity(pay_sum):
    print(f"流动赠送了:{pay_sum} 元")
    
    # 此处省去代码:更新数据库的用户金额
    return True
    

def charge_money(pay_sum):
    
    print(f"充值到账:{pay_sum} 元")
    
    # 此处省去代码:更新数据库的用户金额
    return True


salse_activity(666)
charge_money(666)

# 流动赠送了:666 元
# 充值到账:666 元

软扩是在原根底上新增加了一个函数,相当于是扩大了一个性能。然而又有一个问题了,如果你同时在若干 n 个充值函数都增加充一送一流动,那么就须要写 n 次 salse_activity(666),那就很不美观。那么有请明天的配角装璜器,闪亮退场。

3)智扩:

# 智扩 装璜器


def salse_activity(func):
    """其实就是闭包"""
    def inner(pay_sum):
        print(f"流动赠送了:{pay_sum} 元")
        # 此处省去代码:更新数据库的用户金额
        
        res = func(pay_sum)
        return res
      
    return inner
    

def charge_money(pay_sum):
    
    print(f"充值到账:{pay_sum} 元")
    
    # 此处省去代码:更新数据库的用户金额
    return True

charge_money = salse_activity(charge_money)
charge_money(666)


# 流动赠送了:666 元
# 充值到账:666 元

应用 Python 的装璜器语法糖变形有:

# 装璜器 语法糖


def salse_activity(func):
    """其实就是闭包"""
    def inner(pay_sum):
        
        print(f"流动赠送了:{pay_sum} 元")
        # 此处省去代码:更新数据库的用户金额
        
        res = func(pay_sum)
        return res
    
    return inner
    

@salse_activity    # 就等于是 charge_money = salse_activity(charge_money)
def charge_money(pay_sum):
    
    print(f"充值到账:{pay_sum} 元")
    
    # 此处省去代码:更新数据库的用户金额
    return True


charge_money(666)

# 流动赠送了:666 元
# 充值到账:666 元

装璜器的引入就介绍完了,上面介绍装璜器的具体用法。

2、装璜器参数

装璜器的参数个别会配合 *args**kwargs,看起来更加简介明了。

# 初始化

def decorate_A(func):
    
    print("我是装璜器 A")
    def inner_A(*args):
        print("装璜器 A 被调用")
        res = func(*args)
        print(f"resA:{res}")
        return res + "+ 装璜器 A 返回值"
    
    return inner_A


def decorate_B(func):
    
    print("我是装璜器 B")
    def inner_B(*args):
        print("装璜器 B 被调用")
        res = func(*args)
        print(f"resB:{res}")
        return res
    
    return inner_B

给函数增加装璜器并调用传参:

@decorate_A   # main_func=decorate_A(main_func) = inner_A
def main_func(*args):
    print("我是主函数")
    print(args)
    return True

main_func(*[1, 2, 3], 4, *(5, 6, 7))

"""
我是装璜器 A
装璜器 A 被调用
我是主函数
(1, 2, 3, 4, 5, 6, 7)
resA:True
"""

以上波及到*args,如果不懂得话,能够看我的另一篇博客:[args 和*args](),

3、多层装璜器

多层装璜器是从下往上顺次执行,须要留神的是,被装璜的函数名所指代的函数是始终被装璜器中的内层函数所取代。

# 3. main_func = decorate_A(inner_B)(*args)
@decorate_A   # 2. main_func=decorate_A(inner_B) = inner_A
@decorate_B   # 1. main_func=decorate_B(main_func) = inner_B
def main_func(*args):
    print("我是主函数")
    print(args)
    return "主函数"


res = main_func(*[1, 2, 3], 4, *(5, 6, 7))
print(res)

"""
我是装璜器 B
我是装璜器 A
装璜器 A 被调用
装璜器 B 被调用
我是主函数
main_func:(1, 2, 3, 4, 5, 6, 7)
resB:True
resA:True
主函数 + 装璜器 A 返回值
"""

解释下下面的两个装璜器怎么调用的。

首先:

  1. 调用函数,main_func(*[1, 2, 3], 4, *(5, 6, 7))
  2. 装璜器从下到上执行,先执行 @decorate_B ,main_func 就变成 main_func = decorate_B(main_func) = inner_B 打印后果剖析 :这一步因为调用了decorate_B 函数,所以就打印了 我是装璜器 B
  3. 而后执行装璜器 @decorate_A ,此时有main_func = decorate_A(main_func),然而在上一步装璜器中main_func 曾经变成innder_B,所有main_func = decorate_A(inner_B)

    打印后果剖析 :这一步因为调用了decorate_A 函数,所以就打印了 我是装璜器 A

  4. 最初有 main_func = decorate_A(inner_B)(*args) 打印后果剖析 :1)当调用函数 main_func 时,先执行函数 inner_A,单后打印 装璜器 A 被调用 。2)而后执行传入的参数 inner_B 函数,此时打印 装璜器 B 被调用 。3)执行 inner_B 函数中的函数其实就是被装璜的函数main_func,打印 我是主函数,而后打印main_func:(1, 2, 3, 4, 5, 6, 7)
  5. 解释结束

总结:

装璜器很重要,集体感觉装璜器的设计切实是太奇妙了,然而有点绕不容易了解,倡议多看多练多总结。

参考链接:
https://www.zwjjiaozhu.top/20…

退出移动版