编写装饰器并保存函数的元数据,代码简洁之道
admin
2023-07-19 23:02:04
0

    软件开发中的重要一条真理就是“不要重复自己的工作”。通常当我们需要创建高度重复的代码时,都可以寻找到一个更加优雅的解决方案。

1    给函数添加一个包装,让它做一点额外的工作

    当我们需要让一个函数拥有计时统计、打印日志的功能时,往往选择的方案就是直接在函数体中增加需要的代码。这在只有一两个函数的时候还可以接受,但是如果需要让一个项目中的所有函数都具有这样的功能时,就会变得十分繁琐。

    这时候,就需要我们使用“装饰器”了。示例如下:

from functools import wraps
import time

def logit(func):
    '''
    使用装饰器来打印函数调用信息
    '''

    @wraps(func)
    def wrapper(*args, **kwargs):
        print('start func {}'.format(func.__name__),
              time.strftime('at %Y %m %d %H:%M:%S', time.localtime()))
        result = func(*args, **kwargs)
        print('finish func {}'.format(func.__name__),
              time.strftime('at %Y %m %d %H:%M:%S', time.localtime()))
        return result
    return wrapper

    下面是使用演示:

>>> @logit
def countdown(n):
    while(n > 0):
        n -= 1
>>> countdown(10000000)
start func countdown at 2018 09 16 16:45:23
finish func countdown at 2018 09 16 16:45:24

    只需要在函数定义时为它增加一个装饰器(@logit),这个函数就能告诉我们它开始运行的时间以及结束运行的时间!

    装饰器其实就是一个函数,它可以接受一个函数作为输入并返回一个新的函数作为输出。

    装饰器内部的代码一般会涉及创建一个新的函数,利用*args和**kwargs可以接收任意的参数。在这个函数内部,我们调用原来的输入函数(即被包装的那个函数,它是装饰器的输入参数)并返回它的结果。此时,这个新创建的wrapper函数就会作为装饰器的结果返回,取代了原本的函数。

    需要强调的一点是,装饰器一般来说不会修改调用的签名,也不会修改被包装函数返回的结果。这里使用了*args和**kwargs来确保可以接受任何形式的输入参数。装饰器的返回值几乎总是同调用func(*args,**kwargs)的结果一致,这里的func就是那个未被包装过的原始函数。

2    那装饰器函数中的装饰器@wraps有什么作用

    装饰器@wraps可以用来保存底层的元数据,比如函数名、文档字符串、函数注解以及调用签名。

    如果没有使用该装饰器,获取上一个例子中countdown函数的元数据就会看起来像这样:

>>> countdown.__name__
'wrapper'
>>> countdown.__doc__
>>> countdown.__annotations__

    @wraps的另一个重要特性就是可以通过__wrapped__属性来访问那个被包装的函数,而该属性同时也可以使得装饰器函数可以合适的将底层被包装的函数的签名暴露出来:

>>> from inspect import signature
>>> print(signature(countdown))
(n:int)

编写装饰器并保存函数的元数据,代码简洁之道

相关内容

热门资讯

李涛任中共河南省委常委 据河南日报客户端6月18日消息,中共中央批准:李涛同志任中共河南省委常委。记者:孟亚旭
美媒:以总理对美伊达成谅解备忘... 据凤凰卫视援引美国阿克西奥斯新闻网站报道,美伊谅解备忘录文本公布,以色列的反应备受关注。尽管以总理内...
“空中哨兵”上岗!我市247省... 为紧扣全省公路事业发展部署要求,淮安市公路部门锚定公路数字化、智能化建设,积极落地公路养护“四新技术...
美货运“龙”飞船携科研样品返回... 新华社洛杉矶6月17日电(记者谭晶晶)美国太空探索技术公司的货运“龙”飞船携带大量科研物资和设备返回...
苹果华为高通联发科四大Soc齐... 快科技6月18日消息,今年9月会是2026年消费电子行业热度最高的月份,据数码博主爆料,苹果、高通、...
东莞卓越化学人形机器人润滑解决... 人形机器人模组“隐形标准”缺失:从润滑数据黑盒看国产供应链的突围路径 摘要: 当人形机器人行业沉浸...
刑拘“退衣姐”:“无理由”不是... 网友称为“退衣姐”的北京女子史某,最近被警方刑拘了——4年时间,该女子注册了27个账号,累计恶意退货...
这场大会解码AI变革,锚定产业... 本报记者张伟 2026年6月16日,人工智能+生态大会(AIEC2026)在北京中关村展示中心举办。...
首次加入节电模式,Analog... IT之家 6 月 18 日消息,Analogue Pocket FPGA 复古掌机现已获得 2.6....
2026 6月换机指南:好看好... 2026 6月换机指南:好看好玩还不贵的手机推荐清单 2026 6月换机指南:好看好玩还不贵的手机推...