本文最后更新于:2022年7月4日 上午
Python 装饰器可以对既有方法执行强大的自定义功能, 而且使用@
关键字已经是很方便的使用方式了,但是无法解决需要装饰所有函数的需求,本文记录解决方案。
解决思路
需要用到Python类自带的魔法函数
- 获取到类中所有方法、属性名称
- 过滤得到方法名称
- 通过
__getattribute__
方法获得方法定义
- 重载
__getattribute__
方法,装饰类中的方法,返回装饰后的函数
应该是没有说清楚,上代码吧
示例代码
- 展示一个自动装饰类方法,对函数运行时间进行计时、打印的程序
- 函数输入类定义,使用返回的类定义(装饰过的类)运行时即可得到运行计时结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| from functools import wraps import time
class Test(): def __init__(self) -> None: pass def time_1_sec(self): time.sleep(1) def time_2_sec(self): time.sleep(2) def time_3_sec(self): time.sleep(3) def time_4_sec(self): time.sleep(4)
def foobar(self): self.time_1_sec() self.time_2_sec() self.time_3_sec() self.time_4_sec()
def class_timer(input_class): class MtTimmer(input_class): def __getattribute__(self, name: str): func = super().__getattribute__(name) if str(type(func)) == "<class 'method'>": is_static_method = False try : func_name = func.__name__ except Exception as e: func_name = func.__func__.__name__ func = func.__func__ is_static_method = True
@wraps(func) def wrapper(*args, **kwargs): if is_static_method: args = args[1:]
start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print('func: {_funcname_} runing: {_time_}s'.format(_funcname_=func_name, _time_=format(end_time - start_time, '.6f'))) return res return wrapper return func return MtTimmer
if __name__ == '__main__': warpedTest = class_timer(Test) obj = warpedTest() obj.foobar()
|
1 2 3 4 5
| func: time_1_sec runing: 1.012871s func: time_2_sec runing: 2.004992s func: time_3_sec runing: 3.004082s func: time_4_sec runing: 4.001979s func: foobar runing: 10.024935s
|
参考资料
文章链接:
https://www.zywvvd.com/notes/coding/python/python-wrap-all-method/python-wrap-all-method/