需求1:須要大長臉寫一個功能,測試一下同事二狗的函數的執行效率
import time #引入time模塊
print(time.time())
def func1(): time.sleep(1) print('來了,老弟') def func2(): time.sleep(1) print('回手 掏 ,走位走位....') # # import time start_time = time.time() func1() end_time = time.time() print('此函數的執行時間是%s' % (end_time-start_time)) import time start_time = time.time() func2() end_time = time.time() print('此函數的執行時間是%s' % (end_time-start_time)) # 初版本很差,重複造輪子,測試函數的效率 必須得複製代碼測試 改版:
# 第二版 將臉哥的代碼封裝到函數中,基本完成, import time def func1(): time.sleep(0.6) print('來了,老弟') def func2(): time.sleep(0.5) print('回手 掏 ,走位走位....') def timmer(f): start_time = time.time() f() end_time = time.time() print('此函數的執行時間是%s' % (end_time-start_time)) timmer(func1) timmer(func2)
# 第三版 領導要求在生產環境測試函數的真正的執行效率:線上500個函數 # 線上問題: # 線上的函數你不改變 # 函數的本來的調用方式不能改變 import time def func1(): time.sleep(0.6) print('來了,老弟') def func2(): time.sleep(0.5) print('回手 掏 ,走位走位....') # 本來線上的調用方式: # func1() # func2() # 可是用了臉哥的測試效率的函數以後 def timmer(f): start_time = time.time() f() end_time = time.time() print('此函數的執行時間是%s' % (end_time-start_time)) # 此時你已經改變了原函數的調用方式,而且程序執行了兩遍 func1() timmer(func1)
# 第四版:第三版 沒有改變函數裏面的函數體,可是改變了函數的調用方法,因此要解決:用最少的代碼,解決調用方式一致性的問題。 # 最終完成的需求 func1() 這個指令既要執行func1函數,又要測試效率 import time def func1(): time.sleep(0.6) print('來了,老弟') # # def func2(): # time.sleep(0.5) # print('回手 掏 ,走位走位....') def timmer(f): # f = func1 函數的內存地址 def inner(): start_time = time.time() f() end_time = time.time() print('此函數的執行時間是%s' % (end_time-start_time)) return inner func1 = timmer(func1) # = inner func1() # inner()
# 第五版: 最終基礎版 python提供一個機制,優化,語法糖 @ 上面仍是不夠優化,咱們引入第5種python語法糖@ 示例:func1 = timmer(func1) 就等於@timmer import time def timmer(f): # f = func1 函數的內存地址 def inner(): start_time = time.time() f() end_time = time.time() print('此函數的執行時間是%s' % (end_time - start_time)) return inner @timmer # func1 = timmer(func1) def func1(): time.sleep(0.6) print('來了,老弟') func1() # inner() @timmer def func2(): time.sleep(0.6) print('來le') func2() @timmer def func3(): time.sleep(0.6) print('來') func3()
import time def timmer(f): # f = func1或者func2 函數的內存地址 def inner(*args, **kwargs): start_time = time.time() f(*args, **kwargs) end_time = time.time() print('此函數的執行時間是%s' % (end_time - start_time)) return inner @timmer # func1 = timmer(func1) 在某個函數的上面加上這個 def func1(a): time.sleep(0.6) print('來了,%s' % (a)) func1('alex') @timmer # func2 = timmer(func2) def func2(c,d): time.sleep(0.6) print('%s 年齡 %s' % (c,d)) func2('二狗',21)
import time def timmer(f): # f = func1 函數的內存地址 def inner(*args, **kwargs): start_time = time.time() ret = f(*args, **kwargs) end_time = time.time() print('此函數的執行時間是%s' % (end_time - start_time)) return ret return inner @timmer # func1 = timmer(func1) def func1(a): time.sleep(0.6) print('來了,%s' % (a)) return 666 print(func1('alex')) # print(inner('alex'))
總結:python
一、裝飾器本質其實閉包,
二、裝飾器在不改變原函數的內部函數體以及調用方式的前提下,給函數增長了額外的功能:登陸,註冊,打印日誌,函數效率等等。
# 手寫裝飾器1,先寫閉包: def wrapper(f): def inner(): f() return inner # 手寫裝飾器2,增長參數: def wrapper(f): def inner(*args,**kwargs): f(*args,**kwargs) return inner # 手寫裝飾器3,增長返回值ret,增長函數部分:
def wrapper(f): def inner(*args, **kwargs): ''' 執行被裝飾的函數以前的操做''' print('執行以前', 555) #示例 ret = f(*args, **kwargs) print('執行以後', 666) #示例 ''' 執行被裝飾的函數以後的操做''' return ret return inner @wrapper def func1(): pass func1()