哈喽,各位小夥伴,衆所周知,如果要說你會python, 那麼裝飾器是必備技能,在python開發中,裝飾器的應用也非常廣泛。
不知小夥伴們在編程時有沒有這樣的苦惱:業務邏輯越複雜,函數處理邏輯也會複雜,從而函數中判斷邏輯也會增加,有時還不得不拆分幾個函數輔助完成,這會使得可閱讀性降低,代碼看上去很low,而且這樣做會使得函數通用性降低,程序中必然出現很多重複累贅的代碼。
上面的問題通過類似的裝飾器可以完美解決,而且隻用一個裝飾器名稱。閱讀以下内容你将明白類裝飾器原理,以及一個裝飾器實現:日志記錄、并發運行函數、添加互斥鎖、限制函數執行次數等實例,好了,讓我們進入今天的主題吧,(演示完整代碼在最後,開箱即用)
類裝飾器通用寫法
這是類裝飾器通用寫法
上圖代碼塊内容是類裝飾器最通用的寫法,裝飾器傳參與否,被裝飾函數傳參與否他否可以處理。
類裝飾器運行順序
類裝飾器運行順序
從上圖中的日志輸出我們不難看出類裝飾器運行順序為:①先實例化類裝飾器并執行__init__函數→②調用__call__方法→③調用call方法返回的main方法→④調用main方法返回的函數wapper→⑤運行被裝飾的方法
了解了執行順序,相信你對裝飾器類有一定了解,好了那我們直接看實例
實例1- 并發執行
可以并發執行被裝飾函數,這種做法在自動化中并發執行case,很有用
寫法
運行結果
從打印結果可以看出,打印書序是亂序,說明 并發執行了被裝飾函數,
實例2- 添加互斥鎖
用裝飾器給函數上鎖,簡單、高效、靈活性強,
寫法
運行結果
從打印結果可以看出,沒有并發執行,而是串行,按順序打印
實例3- 記錄日志
寫法
運行結果
從test_log文件裡,可以看出,相應信息被記錄在txt文件中
看了類裝飾器通用寫法,以及相關實例後,依葫蘆畫瓢,整體結構複制後,添加函數,就可以封裝屬于自己的類裝飾器,讓一個裝飾器完成多個功能,相信這對你程序有幫助。
有看不懂的地方,或者需要我幫你封裝的,歡迎留言咨詢,有問必答,相互學習,共赢~~~
示例源碼:
import functools
import copy
from concurrent.futures import ThreadPoolExecutor as TPool
from threading import Lock
import time
import functools
class LeiWrapper: #定義裝飾器類
def __init__(self,*args,**kwargs): #定義類裝飾器初始化方法,用于接收類裝飾器傳入的參數
self.args = args
self.kwargs = kwargs
def main(self): #函數包裝功能 預處理
print("這是類裝飾器中的第一個功能函數")
@functools.wraps(self.func) # 保持函數本身信息不變,比如函數name、注釋信息等
def wapper(*args,**kwargs): # 定義包裹函數,用于接收函數調用時傳入參數
print("4444")
data = self.func(*args,**kwargs) # 調用運行被裝飾的函數
return data # 返回函數處理完的數據
return wapper
def RunBF(self):
@functools.wraps(self.func)
def mm(*arg,**kwarg): #接收函數調用傳入參數
data = ["1","2","3"] #用于并發的數據
with TPool(4) as ex: #啟動有2個線程的線程池
start = time.time()
for i in data:
kwarg[i] = "參數 " str(i) #改變參數
ex.submit(self.func,*arg,**kwarg) #并發執行函數
end = time.time()
print(end - start)
return mm
def LockFun(self):
@functools.wraps(self.func)
def mm(*arg,**kwarg): #接收函數調用傳入參數
with Lock():
funResult = self.func(*arg,**kwarg) #給函數加鎖
return funResult #返回被裝飾函數的返回值
return mm
def logs(self):
@functools.wraps(self.func)
def mm(*arg,**kwarg): #接收函數調用傳入參數
with open("test_log.txt","a ",encoding="UTF-8") as writer:
funResult = self.func(*arg,**kwarg)
message = "函數被執行了,傳入參數為: " str(arg) ",關鍵字參數為:" str(kwarg)
message = message "函數執行結果為: " funResult "\n"
writer.write(message)
return funResult #返回被裝飾函數的返回值
return mm
def __call__(self,func):
self.func = func
if self.kwargs.get("menthod") == "BF": #根據參數判斷裝飾器工作内容
return self.RunBF()
if self.kwargs.get("menthod") == "Lock": #根據參數判斷裝飾器工作内容
return self.LockFun()
if self.kwargs.get("menthod") == "logs": #根據參數判斷裝飾器工作内容
return self.logs()
return self.main()
@LeiWrapper(menthod="logs")
def test(*arg,**kwarg):
time.sleep(2)
print("函數被執行了,傳入參數為: " str(arg) ",關鍵字參數為:" str(kwarg))
return "執行完成"
test("參數1",key="wwwwwww")
test("參數2",key="eeeeeee")
test("參數3",key="rrrrrr")
test("參數4",key="tttt")
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!