需求背景

  • 假若我希望编写一个装饰器,套用给各个测试用例来进行一些统计,诸如,当前用例执行的api,参数,通过与否,预期结果,就必须需要用例方法的相关信息。

    前言

  • 都知道装饰器是在原有函数的基础上,增强一些功能。但是在某些情况下,被装饰的函数的某些属性会被改变

    case1

    ```python import time

def run_time(func): def wrapper(args, **kwargs): “””时间装饰器””” time1 = time.time() func(args, **kwargs) time2 = time.time() cost_time = time2 - time1 return f”函数花了{cost_time}秒” return wrapper

@run_time def test(): “””测试””” print([i for i in range(1, 100001) if i % 200 == 0])

  1. if __name__ == '__main__':
  2. print(test.__name__)
  3. print(test.__doc__)
  4. """
  5. 结果
  6. # wrapper
  7. # 时间装饰器

“””

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/1608527/1651559877011-d8544871-23de-41b0-8261-07e16875da96.png#clientId=u85482d78-b7f8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=740&id=u37b23d85&margin=%5Bobject%20Object%5D&name=image.png&originHeight=925&originWidth=1768&originalType=binary&ratio=1&rotation=0&showTitle=false&size=112511&status=done&style=none&taskId=u2fea421c-899c-449c-81c4-f8a220f1905&title=&width=1414.4)
  2. - 期望它输出的应该是test,测试,但是输出的变成了装饰器的内部函数属性。
  3. - 我们知道@run_time装饰器实际上就等于test = run_time(test),此时我们打印test.__name__实际上test已经指向了wrapper,这样会造成我们打印的时候会打印装饰器的内嵌函数的名字和注释。
  4. <a name="UBzTu"></a>
  5. # 使用wraps装饰器解决
  6. - wraps可以将原函数对象的指定属性复制给包装函数对象, 默认有__module____name____doc____qualname____annotations__或者通过参数选择
  7. ```python
  8. import time
  9. from functools import wraps
  10. def run_time(func):
  11. @wraps(func)
  12. def wrapper(*args, **kwargs):
  13. """时间装饰器"""
  14. time1 = time.time()
  15. func(*args, **kwargs)
  16. time2 = time.time()
  17. cost_time = time2 - time1
  18. return f"函数花了{cost_time}秒"
  19. return wrapper
  20. @run_time
  21. def test():
  22. """测试"""
  23. print([i for i in range(1, 100001) if i % 200 == 0])
  24. if __name__ == '__main__':
  25. print(test.__name__)
  26. print(test.__doc__)
  27. """
  28. 结果:
  29. test
  30. 测试
  31. """

image.png