Python 装饰类中所有自定义函数

本文最后更新于:2022年8月10日 上午

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

参考资料


Python 装饰类中所有自定义函数
https://www.zywvvd.com/notes/coding/python/python-wrap-all-method/python-wrap-all-method/
作者
Yiwei Zhang
发布于
2021年9月29日
许可协议