python 裝飾器的基本使用
知識點
- 簡單的裝飾器
- 帶有參數(shù)的裝飾器
- 帶有自定義參數(shù)的裝飾器
- 類裝飾器
- 裝飾器嵌套
- @functools.wrap裝飾器使用
基礎(chǔ)使用
簡單的裝飾器
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 decorator
test done.
這段代碼中,變量test指向了內(nèi)部函數(shù)wrapper(), 而內(nèi)部函數(shù)wrapper()中又會調(diào)用原函數(shù)test(),因此最后調(diào)用test()時,就會打印'wrapper of decorator' 然后輸出 'test done.'
這里的函數(shù)my_decorator()就是一個裝飾器,它把真正需要執(zhí)行的函數(shù)test()包裹在其中,并且改變了它的行為,但是原函數(shù)test()不變。
上述代碼在Python中更簡單、更優(yōu)雅的表示:
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper()
@my_decorator
def test():
print('test done.')
test
這里的@, 我們稱為語法糖,@my_decorator就相當(dāng)于前面的test=my_decorator(test)語句
如果程序中又其他函數(shù)需要類似裝飾,只需要加上@decorator就可以,提高函數(shù)的重復(fù)利用和程序可讀性
帶有參數(shù)的裝飾器
def args_decorator(func):
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
@args_decorator
def identity(name, message):
print('identity done.')
print(name, message)
identity('changhao', 'hello')
輸出:
wrapper of decorator
identity done.
changhao hello
通常情況下,會把args和*kwargs,作為裝飾器內(nèi)部函數(shù)wrapper()的參數(shù)。 表示接受任意數(shù)量和類型的參數(shù)
帶有自定義參數(shù)的裝飾器
定義一個參數(shù),表示裝飾器內(nèi)部函數(shù)被執(zhí)行的次數(shù),可以寫成這個形式:
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')
輸出:
changhao
changhao
changhao
類裝飾器
類也可以作裝飾器,類裝飾器主要依賴于函數(shù) __call__每當(dāng)調(diào)用一個示例時,函數(shù)__call__()就會被執(zhí)行一次。
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)
@Count
def example():
print('example done.')
example()
example()
輸出:
num of calls is: 1
example done.
num of calls is: 2
example done.
這里定義了類Count,初始化時傳入原函數(shù)func(),而__call__()函數(shù)表示讓變量num_calls自增1,然后打印,并且調(diào)用原函數(shù)。因此我們第一次調(diào)用函數(shù)example()時,num_calls的值是1,而第一次調(diào)用時,值變成了2。
裝飾器的嵌套
import functools
def my_decorator1(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('execute decorator1')
func(*args, **kwargs)
return wrapper
def my_decorator2(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('execute decorator2')
func(*args, **kwargs)
return wrapper
@my_decorator1
@my_decorator2
def test2(message):
print(message)
test2('changhao')
輸出:
execute decorator1
execute decorator2
changhao
類裝飾器
類也可以作裝飾器,類裝飾器主要依賴于函數(shù) __call__每當(dāng)調(diào)用一個示例時,函數(shù)__call__()就會被執(zhí)行一次。
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)
@Count
def example():
print('example done.')
example()
example()
輸出:
num of calls is: 1
example done.
num of calls is: 2
example done.
這里定義了類Count,初始化時傳入原函數(shù)func(),而__call__()函數(shù)表示讓變量num_calls自增1,然后打印,并且調(diào)用原函數(shù)。因此我們第一次調(diào)用函數(shù)example()時,num_calls的值是1,而第一次調(diào)用時,值變成了2。
裝飾器的嵌套
import functools
def my_decorator1(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('execute decorator1')
func(*args, **kwargs)
return wrapper
def my_decorator2(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('execute decorator2')
func(*args, **kwargs)
return wrapper
@my_decorator1
@my_decorator2
def test2(message):
print(message)
test2('changhao')
輸出:
execute decorator1
execute decorator2
changhao
@functools.wrap裝飾器使用
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
@my_decorator
def test3(message):
print(message)
test3.__name__
輸出
test3
通常使用內(nèi)置的裝飾器@functools.wrap,他會保留原函數(shù)的元信息(也就是將原函數(shù)的元信息,拷貝到對應(yīng)的裝飾器里)
裝飾器用法實例
身份認(rèn)證
import functools
def 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
@authenticate
def post_comment(request):
pass
這段代碼中,定義了裝飾器authenticate;而函數(shù)post_comment(),則表示發(fā)表用戶對某篇文章的評論。每次調(diào)用這個函數(shù)前,都會檢查用戶是否處于登錄狀態(tài),如果是登錄狀態(tài),則允許這項操作;如果沒有登錄,則不允許。
日志記錄
import time
import functools
def 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_time
def calculate_similarity(times):
pass
這里裝飾器log_execution_time記錄某個函數(shù)的運行時間,并返回其執(zhí)行結(jié)果。如果你想計算任何函數(shù)的執(zhí)行時間,在這個函數(shù)上方加上@log_execution_time即可。
總結(jié)
所謂裝飾器,其實就是通過裝飾器函數(shù),來修改原函數(shù)的一些功能,使得原函數(shù)不需要修改。
以上就是python 裝飾器的基本使用的詳細(xì)內(nèi)容,更多關(guān)于python 裝飾器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python中yield關(guān)鍵字及與return的區(qū)別詳解
這篇文章主要介紹了Python中yield關(guān)鍵字及與return的區(qū)別詳解,帶有 yield 的函數(shù)在 Python 中被稱之為 generator生成器,比如列表所有數(shù)據(jù)都在內(nèi)存中,如果有海量數(shù)據(jù)的話將會非常耗內(nèi)存,想要得到龐大的數(shù)據(jù),又想讓它占用空間少,那就用生成器,需要的朋友可以參考下2023-08-08
Python numpy生成矩陣、串聯(lián)矩陣代碼分享
這篇文章主要介紹了Python numpy生成矩陣、串聯(lián)矩陣代碼分享,具有一定參考價值,需要的朋友可以了解下。2017-12-12
基于 Django 的手機管理系統(tǒng)實現(xiàn)過程詳解
這篇文章主要介紹了基于 Django 的手機管理系統(tǒng)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08
Python保存dict字典類型數(shù)據(jù)到Mysql并自動創(chuàng)建表與列
這篇文章主要介紹了Python保存dict字典類型數(shù)據(jù)到Mysql并自動創(chuàng)建表與列,字典是另一種可變?nèi)萜髂P?,且可存儲任意類型對象,想了解更多?nèi)容的小伙伴可以和小編一起進入下面文章學(xué)習(xí)更多內(nèi)容,希望對你有所幫助2022-02-02

