装饰器中添加参数

一个简单场景:我有一个给函数计时的装饰器,现在我想给函数运行的时间添加一个时间偏移量time_lag,该时间偏移量不是常数,想通过把该参数传入装饰器中来实现。

  • 实现方式1:
import time
from functools import wraps
def timer_func(func,time_lag):
    @wraps(func)
    def wer(*args,**kwargs):
        t1=time.time()
        r=func(*args,**kwargs)
        t2=time.time()
        cost=t2-t1+time_lag
        print('time cost %s'%cost)
        return r
    return wer

def func(n:int):
    while n>0:
        n=n-1
    return n
a=timer_func(func,time_lag=10)
a(1000000)

但是这样的实现方式,就无法语法糖@,每次都要通过函数调用来实现,就失去了装饰器简明、方便的特点了。

因此用另一种实现方式,只需要在原有装饰函数外面再嵌套一层外函数,将想传入装饰器的函数传入最外层函数即可,实现方式如下:

  • 实现方式2:
from functools import wraps
import time
def timer(time_lag):

    def decorator(func):
        @wraps(func)
        def wer(*args, **kwargs):
            t1 = time.time()
            r = func(*args, **kwargs)
            t2 = time.time()
            cost = t2 - t1
            res=cost+time_lag
            print('time cost %s' % res)
            return func(*args, **kwargs)#返回函数本身结果
        return wer#返回内函数
    return decorator#返回外函数

def func(n:int):
    '''
    this is a func test
    :param n:
    :return:
    '''
    while n>0:
        n=n-1
    return n

>>>a=timer(10)#返回外函数,#传入time_lag=10
>>>print(a)
<function timer.<locals>.decorator at 0x000002027D8E5E50>
>>>b=a(func)#返回内函数
>>>print(b)
<function func at 0x000002027D9434C0>
>>>c=b(999999)#调用内函数返回结果
>>>print(c)
time cost 10.069796323776245
0

上述逐步调用的过程只是为了清晰的展示,该函数看起来复杂,实际上本质思想还是闭包的思想,只是在装饰器外再嵌套了一层外函数。每个外函数返回的是它的下一级内函数。最内层函数返回的是调用函数的结果。该方式还可以通过语法糖简明的调用:

@timer(10)#传入time_lag=10
def func(n:int):

    while n>0:
        n=n-1
    return n
>>>func(99999)
time cost 10.008002042770386

@timer(20)#传入time_lag=20
def func1(n:int):

    while n>0:
        n=n-1
    return n
>>>func1(22222222)
time cost 21.447203874588013
  • 创建一个带参数的日志装饰器

创建一个日志装饰器,该日志的输出等级、名称、信息通过传参传入装饰器中

def logged(level,name=None,message=None):

    def decorator(func):
        logname=name if name else func.__module__
        log=logging.getLogger(logname)
        logmsg=message if message else func.__name__

        @wraps(func)
        def wraper(*args,**kwargs):
            log.log(level,message)
            return func(*args,**kwargs)
        return wraper
    return decorator

@logged(logging.DEBUG,'test_name')
def func(a):
    return a+1
1 声望
2 粉丝
0 条评论
推荐阅读
python迭代器与生成器详解
a是一个列表,本身也是一个迭代器(iterator);for循环能够遍历的一定是iterator,在遍历时会默认调用迭代器的iter()方法,将其显示出来,即等价于:

千翻娃儿阅读 1.2k

数据结构与算法:二分查找
一、常见数据结构简单数据结构(必须理解和掌握)有序数据结构:栈、队列、链表。有序数据结构省空间(储存空间小)无序数据结构:集合、字典、散列表,无序数据结构省时间(读取时间快)复杂数据结构树、 堆图二...

白鲸鱼9阅读 5.3k

滚蛋吧,正则表达式!
你是不是也有这样的操作,比如你需要使用「电子邮箱正则表达式」,首先想到的就是直接百度上搜索一个,然后采用 CV 大法神奇地接入到你的代码中?

良许3阅读 1.4k

搭个ChatGPT算法模型,从哪开始?
最近 ChatGPT 很火,火到了各行各业。记得去年更多的还是码农最新体验后拿它搜代码,现在各行各业都进来体验,问它咋理财、怎么写报告和给小孩起名。😂 也因此让小傅哥在头条的一篇关于 ChatGPT 的文章都有了26万...

小傅哥6阅读 1.1k

封面图
程序员适合创业吗?
大家好,我是良许。从去年 12 月开始,我已经在视频号、抖音等主流视频平台上连续更新视频到现在,并得到了不错的评价。每个视频都花了很多时间精力用心制作,欢迎大家关注哦~考虑到有些小伙伴没有看过我的视频,...

良许3阅读 1.2k

Ubuntu20.04 从源代码编译安装 python3.10
Ubuntu 22.04 Release DateUbuntu 22.04 Jammy Jellyfish is scheduled for release on April 21, 2022If you’re ready to use Ubuntu 22.04 Jammy Jellyfish, you can either upgrade your current Ubuntu syste...

ponponon1阅读 4.5k评论 1

PyCharm 激活破解教程, 2023 年 2 月亲测有用
本文分享一下PyCharm 2022.2.3 版本最新激活破解教程,注意不要使用太新的版本,都是 Jetbrains 产品,本文专门配上了 Pycharm 的图片,跟着下面教程一步一步来即可。

程序员徐公阅读 7.9k评论 1

1 声望
2 粉丝
宣传栏