元编程之给函数添加一个包装

前言

软件开发中最重要的一条真理是"don’t repeat yourself",即不要重复自己的工作。也就是说,在任何时候,需要创建高度重复的代码或者需要复制粘贴源码时,通常这时都需要寻找一个更加优雅的解决方案!!!在PYTHON中,我们称这为"元编程"!
元编程的主要目的是创建函数和类,并用它们来操纵代码;例如:修改、生成或包装已存在的代码。python中基于这个目的的主要特性包括装饰器,类装饰器以及元类。

问题

给函数加上一个包装层(wrapper layer)来添加额外的处理,例如记录日志,记录运行时间等。

解决方案

# coding:utf-8

import time
from functools import wraps


def timethis(func):
    """
    Decorator that reports the execution time.
    :param func:
    :return:
    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(func.__name__, end-start)
        return result
    return wrapper


@timethis
def countdown(n):
    while n > 0:
        n -= 1


if __name__ == '__main__':
    # countdown(10000)
    print(countdown.__name__) # 函数名
    print(countdown.__doc__) # 文档字符串
    print(countdown.__annotations__) # 注解

结果

C:\Users\tianming\AppData\Local\Programs\Python\Python37-32\python.exe H:/test/wrapAfunc.py
countdown 0.0009984970092773438
countdown

    counts down
    :param n:
    :return:
    
{'n': <class 'int'>}

Process finished with exit code 0

去掉@wraps(func)结果

C:\Users\tianming\AppData\Local\Programs\Python\Python37-32\python.exe H:/test/wrapAfunc.py
countdown 0.0009801387786865234
wrapper
None
{}

Process finished with exit code 0

discuss

1.在装饰器内部一般会涉及创建一个新的函数,利用*args和**kwargs来接受任意的参数。(wrapper正是这么做的)
2.在wrapper函数内部需要调用被包装的函数(它是装饰器的输入参数)并返回它的结果。
3.在这个包装函数中也可以添加任何想要添加的代码,例如计时处理等。
4.新创建的wrapper函数会作为装饰器的结果返回,取代了原来的函数。
5.装饰器一般来说不会修改函数的签名,也不会修改被包装函数返回的结果

当把写好的装饰器用在一个函数上时,为了不丢失被装饰函数的元数据(如:函数名,文档字符串,函数注解,调用签名),应该总是在底层被包装函数上添加functools库中的@wraps装饰器

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你抱着的是只熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值