1、引入場景:
檢查代碼的運行時間
import time def func(): start = time.time() time.sleep(0.12) print('看看我運行了多長時間!') end = time.time() print('此段代碼運行時長為:%s'%(end - start)) func()
如果有大量的函數要檢查,這樣加入代碼太費功夫!考慮提取為一個函數,要檢查時直接調用即可
def check_time(f): start = time.time() time.sleep(0.12) f() end = time.time() print('此段代碼運行時長為:%s' % (end - start)) check_time(func)
還是有問題,有人嫌每次都去調用該函數很麻煩!
能不能,在不修改要測試遠行時長的函數的調用方式前提下,還想在原來的函數前后添加測試時長功能?
def timing(f): # 裝飾器函數 def inner(): start = time.time() time.sleep(0.12) f() # 被裝飾函數 end = time.time() print('此段代碼運行時長為:%s' % (end - start)) return inner func = timing(func) func()
這里就可以定義裝飾器函數了,用來裝飾其他函數,添加相關功能的函數叫裝飾器函數
2、語法糖的使用
@timing # @裝飾器函數名 相當於前面函數調用前的賦值:func_to = timing(func_to) def func_to(): # 被裝飾的函數 a = 1000000 b = 1223434 return a * b func_to()
3、裝飾器的作用
不想修改函數的調用方式 但是還想在原來的函數前后添加功能
上面的例子中timmer就是一個裝飾器函數,只是對一個函數 有一些裝飾作用
4、裝飾帶參數的函數
def timing_arg(f): def inner(a): start = time.time() re = f(a) end = time.time() print('此段代碼運行時長為:%s' % (end - start)) return re return inner @timing_arg def func_have_arg(a): result = a * 10000000 return result
5、裝飾帶可變參數的函數
1 def wrapper(f): # 裝飾器函數,f是被裝飾的函數 2 def inner(*args, **kwargs): 3 '''在被裝飾函數之前要做的事''' 4 ret = f(*args, **kwargs) # 被裝飾的函數 5 '''在被裝飾函數之后要做的事''' 6 return ret 7 8 return inner 9 10 @wrapper # 語法糖 @裝飾器函數名 11 def func_101(a, b): # 被裝飾的函數 12 time.sleep(0.01) 13 print('老板好同事好大家好', a, b) 14 return '新年好' 15 16 print(func_101(100, b=200))
6、編程原則: 開放封閉原則#
開放 : 對擴展是開放的
封閉 : 對修改是封閉的