# -*-coding=utf-8 -*-
#實現一個函數執行后計算執行時間的功能
__author__ = 'piay' import time, functools def foo(): ''' 定義一個普通函數 :return: ''' print 'this is foo' foo() ''' 這里如果我們需要查看函數執行時間,修改為: ''' def foo1(): start_time = time.clock() print 'this is foo1' end_time = time.clock() print '執行時間為:', end_time - start_time foo1() ''' 如果我們其他的函數也需要執行時間,或者這個函數不需要執行時間,那么我們就需要復制到其他的函數中去 這是一種最差的方法 ''' def foo3(): print 'this is foo3' def timeit(func): ''' 我們可以考慮重新定義一個函數timeit,將foo的引用傳遞給他, 然后在timeit中調用foo並進行計時,這樣,我們就達到了不改動foo定義的目的 :param func: 傳入的函數 :return: ''' start_time = time.clock() func() end_time = time.clock() print 'used:', end_time - start_time timeit(foo3) ''' 這樣寫修改調用部分的代碼。原本我們是這樣調用的:foo3(),現在變成timeit(foo),這樣的話,如果foo在N處都被調用了, 你就不得不去修改這N處的代碼。或者更極端的,考慮其中某處調用的代碼無法修改這個情況,比如:這個函數是你交給別人使用的。 ''' ''' 想想辦法不修改調用的代碼;如果不修改調用代碼,也就意味着調用foo()需要產生調用timeit(foo)的效果。我們可以想到將timeit賦值給foo, 但是timeit似乎帶有一個參數……想辦法把參數統一吧!如果timeit(foo)不是直接產生調用效果, 而是返回一個與foo參數列表一致的函數的話……就很好辦了,將timeit(foo)的返回值賦值給foo,然后,調用foo()的代碼完全不用修改! ''' def foo4(): print 'this is foo4' # 定義一個計時器,傳入一個,並返回另一個附加了計時功能的方法 def timeit4(func): # 定義一個內嵌的包裝函數,給傳入的函數加上計時功能的包裝 def wrapper(): start_time = time.clock() func() end_time = time.clock() print 'used:', end_time - start_time # 將包裝后的函數返回 return wrapper foo_1 = timeit(foo4) ''' 上面的代碼就類似裝飾器了,可以修改為如下: ''' @timeit4 # 定義上加上這一行與另外寫foo = timeit(foo)完全等價 def foo5(): print 'this is foo5' foo5() ''' ----------------------------------------------- 使用functools.wraps(func)裝飾器實現功能 ''' def timeit_3_for_wraps(func): @functools.wraps(func) def wrapper(): start=time.clock() func() end=time.clock() print 'used:',end-start return wrapper @timeit_3_for_wraps def foo6(): print 'this is foo6' foo6()
這里實現一個完整的判斷是否帶參數的裝飾器:
# -*-coding=utf-8 -*- __author__ = 'piay' import functools, time ''' 一個函數執行前打印開始執行,執行完后打印執行完成,記錄執行時間 ''' def log(text): if callable(text): # 參數如果是函數,說明裝飾器不帶參傳過來,text是一個函數 @functools.wraps(text) def wrapper(*args, **kwargs): start = time.clock() print '這是不帶參數的裝飾器,開始執行' f = text(*args, **kwargs) #執行本身的函數 text() end = time.clock() print "結束執行:", end - start return f # 返還原函數 return wrapper elif not callable(text): # text是參數,不是函數 def decarator(func): @functools.wraps(func) def warpper(*args, **kwargs): start = time.clock() print '這是不帶參數的裝飾器,開始執行,參數為:'+text f = func(*args, **kwargs) end=time.clock() print "結束執行:",end-start return f #返還原函數 return warpper return decarator else: print '請檢查是否正確' @log def add1(x,y): print x+y @log('222') def add2(x,y): print x+y add1(1,2) add2(2,3)
執行結果:
D:\Python27\python.exe D:/Python/functools_study/完整的裝飾器.py
這是不帶參數的裝飾器,開始執行
3
結束執行: 5.08444509009e-05
這是不帶參數的裝飾器,開始執行,參數為:222
5
結束執行: 2.49333364995e-05
Process finished with exit code 0