Python 裝飾器可以對既有方法執行強大的自定義功能, 而且使用 @
關鍵字已經是很友善的使用方式了,但是無法解決需要裝飾所有函數的需求,本文記錄解決方案。
解決思路
需要用到Python類自帶的魔法函數
- 擷取到類中所有方法、屬性名稱
- 過濾得到方法名稱
- 通過
方法獲得方法定義__getattribute__
- 重載
方法,裝飾類中的方法,傳回裝飾後的函數__getattribute__
應該是沒有說清楚,上代碼吧
示例代碼
- 展示一個自動裝飾類方法,對函數運作時間進行計時、列印的程式
- 函數輸入類定義,使用傳回的類定義(裝飾過的類)運作時即可得到運作計時結果
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()
複制
- 輸出
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://blog.csdn.net/weixin_36179862/article/details/102829018