温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

python中如何使用装饰器

发布时间:2021-07-10 15:25:24 来源:亿速云 阅读:145 作者:Leah 栏目:互联网科技

本篇文章为大家展示了python中如何使用装饰器,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

带参数装饰器结构

大家都知道了装饰器是用来拓展函数功能的,但是别忘了装饰器本身也是函数,当然也可以通过给装饰器增加参数来拓展功能。

我们继续昨天的案例讲解带参数装饰器:现在客户又提需求了,客户发现周一到周五收银机的帐目很清楚,但是周六日账目有点混乱。客户希望收银机把周六和周日的所有交易记录保存到日志文件中,周一到周五的交易记录不需要保存。

分析客户需求,按照我们昨天学习的装饰器的内容,可以很快想到解决方案,再写一个装饰器用来保存交易记录。但是这里有一个难点,客户要求周一至周五的不保存,周六周日的保存,怎么办呢?

在这里就需要用到带参数装饰器了,具体代码如下:

import functools
from datetime import datetime
# 这行代码是获取当前是星期几,周一对应对应1,周六对应6,周日对应7
# day_week = datetime.now().isoweekday()  # 今天是周二,明天周三,不会触发记录日志的条件,暂注释,方便测试
day_week = 7  # 为了测试,假定今日是周日。实际使用时注释这行,取消注释上面一行。

def check_week(chk):
    def inner(func):
        @functools.wraps(func)
        def inner_chk(*args, **kwargs):
            if chk:
                with open('log.txt', mode='a', encoding='utf8') as f:
                    f.write(f'交易记录:折扣值是{args[0]},商品单价{args[1]},商品数量{args[2]},交易时间是{datetime.now()}\n')
            return func(*args, **kwargs)
        return inner_chk
    return inner

def checkdisct(func):
    @functools.wraps(func)
    def inner(*args, **kwargs):
        disct = args[0]
        if disct >= 0.5 and disct <= 1:
            print('折扣值合理!')
            return func(*args, **kwargs)
        else:
            print('折扣值不合理!')
    return inner

def checkpwd(func):
    @functools.wraps(func)
    def inner(*args, **kwargs):
        pwd = input('请输入密码:')
        if pwd == "123456":
            print("密码正确!")
            return func(*args, **kwargs)
        else:
            print('密码错误!')
    return inner

# 判断不是星期六和日则设置day_week为0,不触发记录log;若是周六、周日会触发记录log。
if day_week != 6 or day_week != 7:  
    day_week = 0

@checkpwd
@checkdisct
@check_week(day_week)
def count(x, prince, number):
    '''功能:计算商品应付款和实付款的函数。
参数:x是float型,指定折扣额度;prince是float型,指定商品的单价;number是int型,指定商品的数量。'''
    result = prince * number
    pay = result * x
    print(f'总价是{result}元,实付{pay}元')

count(0.8, 2.88, 100)
count(0.3, 2.88, 100)

out:
请输入密码:123456
密码正确!
折扣值合理!
总价是288.0元,实付230.4元
请输入密码:1
密码错误!

python中如何使用装饰器

测试结果完全满足客户的需求,实现了周一至五不记录交易log,周六日记录交易log。

带参数装饰器详解

直接读上面大段代码对于装饰器运用不熟练的朋友可能会有些懵懂,下面详细讲解带参数装饰器。

带参数装饰器至少有3层结构,即最少包含3层def和3层return。

  1. 第一层:负责接收装饰器自身的参数,再返回第二层函数。

  2. 第二层:负责接收被装饰的函数,再返回第三层函数。

  3. 第三层:这一层做的事情很多,按功能划分为3块。

    1. 负责接收被装饰函数的参数。

    2. 对装饰器自身的参数进行解析处理,若其满足某条件则做某动作,不满足条件则不做动作(或做别的动作)。

    3. 返回被装饰的函数及其参数。

def check_week(chk):  # 带参数装饰器,chk是判断条件,chk不是0则记录交易日志,chk是0则不记录
    def inner(func):  # func是被装饰的函数名
        @functools.wraps(func)
        def inner_chk(*args, **kwargs):  # *args和**kwargs是被装饰的函数参数
            if chk:  #判断条件是否满足,若不为0则将交易记录和交易时间保存到log.txt文件
                with open('log.txt', mode='a', encoding='utf8') as f:  
                    f.write(f'交易记录:折扣值是{args[0]},商品单价{args[1]},商品数量{args[2]},交易时间是{datetime.now()}\n')
            return func(*args, **kwargs)  # 返回被装饰的函数及其参数
        return inner_chk  # 返回第三层函数inner_chk
    return inner  # 返回第二层函数inner

以上案例详细讲解了带参数装饰器的构造,要学习装饰器必须多加练习才能真正掌握。

带参数装饰器的运用场景

关于带参数装饰器的运用场景有很多,比较常见的有是否记录业务日志,是否生成性能日志,使用测试数据库运行或使用生产数据库运行等等,具体要因业务需求而定。

装饰器的补充运用

关于装饰器的运用,除了可以自己写的装饰器用,也有一些官方或第三方提供的装饰器非常好用。例如之前有提及的@functools.wraps装饰器。

这里再补充一个numba的jit装饰器,功能是通过即时编译的方法提升python函数运行效率。在涉及大量循环运算的场合建议尝试一下。以下是测试代码。

from numba import jit
import time

@jit
def fib(n):
    if n <= 2:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)

start = time.time()
print(fib(40))
end = time.time()
print(f"用时:{end - start}秒")

out:
102334155
用时:1.001574993133545秒

大家猜猜如果注释掉@jit,运行时间时间需要多少秒?

python中如何使用装饰器

上述内容就是python中如何使用装饰器,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI