python中如何使用装饰器
本篇文章为大家展示了python中如何使用装饰器,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
创新互联公司是专业的垦利网站建设公司,垦利接单;提供成都网站设计、成都做网站,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行垦利网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!
带参数装饰器结构
大家都知道了装饰器是用来拓展函数功能的,但是别忘了装饰器本身也是函数,当然也可以通过给装饰器增加参数来拓展功能。
我们继续昨天的案例讲解带参数装饰器:现在客户又提需求了,客户发现周一到周五收银机的帐目很清楚,但是周六日账目有点混乱。客户希望收银机把周六和周日的所有交易记录保存到日志文件中,周一到周五的交易记录不需要保存。
分析客户需求,按照我们昨天学习的装饰器的内容,可以很快想到解决方案,再写一个装饰器用来保存交易记录。但是这里有一个难点,客户要求周一至周五的不保存,周六周日的保存,怎么办呢?
在这里就需要用到带参数装饰器了,具体代码如下:
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 密码错误!
测试结果完全满足客户的需求,实现了周一至五不记录交易log,周六日记录交易log。
带参数装饰器详解
直接读上面大段代码对于装饰器运用不熟练的朋友可能会有些懵懂,下面详细讲解带参数装饰器。
带参数装饰器至少有3层结构,即最少包含3层def和3层return。
第一层:负责接收装饰器自身的参数,再返回第二层函数。
第二层:负责接收被装饰的函数,再返回第三层函数。
第三层:这一层做的事情很多,按功能划分为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中如何使用装饰器
分享URL:http://ybzwz.com/article/pgejji.html