python 裝飾器的基本使用
def my_decorator(func): def wrapper(): print(’wrapper of decorator’) func() return wrapper()def test(): print(’test done.’)test = my_decorator(test)test輸出:wrapper of decoratortest done.
這段代碼中,變量test指向了內部函數wrapper(), 而內部函數wrapper()中又會調用原函數test(),因此最后調用test()時,就會打印’wrapper of decorator’ 然后輸出 ’test done.’
這里的函數my_decorator()就是一個裝飾器,它把真正需要執行的函數test()包裹在其中,并且改變了它的行為,但是原函數test()不變。
上述代碼在Python中更簡單、更優雅的表示:
def my_decorator(func): def wrapper(): print(’wrapper of decorator’) func() return wrapper()@my_decoratordef test(): print(’test done.’)test
這里的@, 我們稱為語法糖,@my_decorator就相當于前面的test=my_decorator(test)語句
如果程序中又其他函數需要類似裝飾,只需要加上@decorator就可以,提高函數的重復利用和程序可讀性
帶有參數的裝飾器def args_decorator(func): def wrapper(*args, **kwargs): print(’wrapper of decorator’) func(*args, **kwargs) return wrapper@args_decoratordef identity(name, message): print(’identity done.’) print(name, message)identity(’changhao’, ’hello’)輸出:wrapper of decoratoridentity done.changhao hello
通常情況下,會把args和*kwargs,作為裝飾器內部函數wrapper()的參數。 表示接受任意數量和類型的參數
帶有自定義參數的裝飾器定義一個參數,表示裝飾器內部函數被執行的次數,可以寫成這個形式:
def repeat(num): def my_decorator(func): def wrapper(*args, **kwargs): for i in range(num):func(*args, **kwargs) return wrapper return my_decorator@repeat(3)def showname(message): print(message)showname(’changhao’)輸出:changhaochanghaochanghao類裝飾器
類也可以作裝飾器,類裝飾器主要依賴于函數 __call__每當調用一個示例時,函數__call__()就會被執行一次。
class Count: def __init__(self, func): self.func = func self.num_calls = 0 def __call__(self, *args, **kwargs): self.num_calls += 1 print(’num of calls is: {}’.format(self.num_calls)) return self.func(*args, **kwargs)@Countdef example(): print(’example done.’)example()example()輸出:num of calls is: 1example done.num of calls is: 2example done.
這里定義了類Count,初始化時傳入原函數func(),而__call__()函數表示讓變量num_calls自增1,然后打印,并且調用原函數。因此我們第一次調用函數example()時,num_calls的值是1,而第一次調用時,值變成了2。
裝飾器的嵌套import functoolsdef my_decorator1(func): @functools.wraps(func) def wrapper(*args, **kwargs): print(’execute decorator1’) func(*args, **kwargs) return wrapperdef my_decorator2(func): @functools.wraps(func) def wrapper(*args, **kwargs): print(’execute decorator2’) func(*args, **kwargs) return wrapper@my_decorator1@my_decorator2def test2(message): print(message)test2(’changhao’)輸出:execute decorator1execute decorator2changhao類裝飾器
類也可以作裝飾器,類裝飾器主要依賴于函數 __call__每當調用一個示例時,函數__call__()就會被執行一次。
class Count: def __init__(self, func): self.func = func self.num_calls = 0 def __call__(self, *args, **kwargs): self.num_calls += 1 print(’num of calls is: {}’.format(self.num_calls)) return self.func(*args, **kwargs)@Countdef example(): print(’example done.’)example()example()輸出:num of calls is: 1example done.num of calls is: 2example done.
這里定義了類Count,初始化時傳入原函數func(),而__call__()函數表示讓變量num_calls自增1,然后打印,并且調用原函數。因此我們第一次調用函數example()時,num_calls的值是1,而第一次調用時,值變成了2。
裝飾器的嵌套import functoolsdef my_decorator1(func): @functools.wraps(func) def wrapper(*args, **kwargs): print(’execute decorator1’) func(*args, **kwargs) return wrapperdef my_decorator2(func): @functools.wraps(func) def wrapper(*args, **kwargs): print(’execute decorator2’) func(*args, **kwargs) return wrapper@my_decorator1@my_decorator2def test2(message): print(message)test2(’changhao’)輸出:execute decorator1execute decorator2changhao@functools.wrap裝飾器使用
import functoolsdef my_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print(’wrapper of decorator’) func(*args, **kwargs) return wrapper@my_decoratordef test3(message): print(message)test3.__name__ 輸出test3
通常使用內置的裝飾器@functools.wrap,他會保留原函數的元信息(也就是將原函數的元信息,拷貝到對應的裝飾器里)
裝飾器用法實例身份認證import functoolsdef authenticate(func): @functools.wraps(func) def wrapper(*args, **kwargs): request = args[0] if check_user_logged_in(request): return func(*args, **kwargs) else: raise Exception(’Authentication failed’) return wrapper@authenticatedef post_comment(request): pass
這段代碼中,定義了裝飾器authenticate;而函數post_comment(),則表示發表用戶對某篇文章的評論。每次調用這個函數前,都會檢查用戶是否處于登錄狀態,如果是登錄狀態,則允許這項操作;如果沒有登錄,則不允許。
日志記錄import timeimport functoolsdef log_execution_time(func): @functools.wraps(func) def wrapper(*args, **kwargs): start = time.perf_counter() res = func(*args, **kwargs) end = time.perf_counter() print(’{} took {} ms’.format(func.__name__, (end - start) * 1000)) return wrapper@log_execution_timedef calculate_similarity(times): pass
這里裝飾器log_execution_time記錄某個函數的運行時間,并返回其執行結果。如果你想計算任何函數的執行時間,在這個函數上方加上@log_execution_time即可。
總結所謂裝飾器,其實就是通過裝飾器函數,來修改原函數的一些功能,使得原函數不需要修改。
以上就是python 裝飾器的基本使用的詳細內容,更多關于python 裝飾器的資料請關注好吧啦網其它相關文章!
相關文章: