您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“怎么創(chuàng)建和使用Python裝飾器”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“怎么創(chuàng)建和使用Python裝飾器”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。
當(dāng)您需要更改函數(shù)的行為而不修改函數(shù)本身時,您將使用裝飾器。一些很好的例子是當(dāng)您想要添加日志記錄、測試性能、執(zhí)行緩存、驗(yàn)證權(quán)限等時。
當(dāng)您需要在多個函數(shù)上運(yùn)行相同的代碼時,您也可以使用裝飾器。這可以避免您編寫重復(fù)的代碼。
為了更好地理解裝飾器的工作原理,您應(yīng)該先了解一些概念。
函數(shù)是一個對象。因此,可以將函數(shù)分配給變量??梢詮脑撟兞吭L問該函數(shù)。
def my_function(): print('I am a function.') # Assign the function to a variable without parenthesis. We don't want to execute the function. description = my_function
# Accessing the function from the variable I assigned it to. print(description()) # Output 'I am a function.'
2. 一個函數(shù)可以嵌套在另一個函數(shù)中。
def outer_function(): def inner_function(): print('I came from the inner function.') # Executing the inner function inside the outer function. inner_function()
outer_function() # Output I came from the inner function.
請注意,inner_function在outer_function內(nèi)部. 如果我嘗試執(zhí)行inner_function外部,outer_function我會收到 NameError 異常。
inner_function() Traceback (most recent call last): File "/tmp/my_script.py", line 9, in <module> inner_function() NameError: name 'inner_function' is not defined
3. 由于一個函數(shù)可以嵌套在另一個函數(shù)中,所以它也可以被返回。
def outer_function(): '''Assign task to student''' task = 'Read Python book chapter 3.' def inner_function(): print(task) return inner_function homework = outer_function()
homework() # Output 'Read Python book chapter 5.'
4. 一個函數(shù)可以作為參數(shù)傳遞給另一個函數(shù)。
def friendly_reminder(func): '''Reminder for husband''' func() print('Don\'t forget to bring your wallet!') def action(): print('I am going to the store buy you something nice.')
# Calling the friendly_reminder function with the action function used as an argument. friendly_reminder(action) # Output I am going to the store buy you something nice. Don't forget to bring your wallet!
為了在 Python 中創(chuàng)建裝飾器函數(shù),我創(chuàng)建了一個將函數(shù)作為參數(shù)的外部函數(shù)。還有一個內(nèi)部函數(shù)環(huán)繞裝飾函數(shù)。
以下是基本 Python 裝飾器的語法:
def my_decorator_func(func): def wrapper_func(): # Do something before the function. func() # Do something after the function. return wrapper_func
要使用裝飾器,您可以將其附加到一個函數(shù),就像您在下面的代碼中看到的那樣。我們通過將裝飾器的名稱直接放在我們想要使用它的函數(shù)上方來使用裝飾器。你用一個@符號作為裝飾器函數(shù)的前綴。
@my_decorator_func def my_func(): pass
這是一個簡單的例子。此裝飾器記錄執(zhí)行函數(shù)的日期和時間:
from datetime import datetime def log_datetime(func): '''Log the date and time of a function''' def wrapper(): print(f'Function: {func.__name__}\nRun on: {datetime.today().strftime("%Y-%m-%d %H:%M:%S")}') print(f'{"-"*30}') func() return wrapper @log_datetime def daily_backup(): print('Daily backup job has finished.') daily_backup() # Output Daily backup job has finished. Function: daily_backup Run on: 2021-06-06 06:54:14 ---------------------------
裝飾器可以將參數(shù)傳遞給它們。要向裝飾器添加參數(shù),我將*args 和 **kwargs添加到內(nèi)部函數(shù)。
*args采取的任何類型的參數(shù),數(shù)據(jù)類型不受限制,比如10,True,或'Brandon'。
**kwargs采取任何類型的關(guān)鍵字參數(shù),例如count=99, is_authenticated=True, 或name='Brandon'。
這是一個帶參數(shù)的裝飾器:
def my_decorator_func(func): def wrapper_func(*args, **kwargs): # Do something before the function. func(*args, **kwargs) # Do something after the function. return wrapper_func @my_decorator_func def my_func(my_arg): '''Example docstring for function''' pass
裝飾者隱藏他們正在裝飾的函數(shù)。如果我檢查__name__or__doc__方法,我們會得到一個意想不到的結(jié)果。
print(my_func.__name__) print(my_func.__doc__) # Output wrapper_func None
為了解決這個問題,我將使用functools. Functools 包裝將使用裝飾函數(shù)屬性更新裝飾器。
from functools import wraps def my_decorator_func(func): @wraps(func) def wrapper_func(*args, **kwargs): func(*args, **kwargs) return wrapper_func @my_decorator_func def my_func(my_args): '''Example docstring for function''' pass
現(xiàn)在我收到了我期待的輸出。
print(my_func.__name__) print(my_func.__doc__) # Output my_func Example docstring for function
我創(chuàng)建了一個裝飾器來測量函數(shù)的內(nèi)存和速度。我們將使用裝飾器通過四種方法測試性能列表生成:范圍、列表理解、追加和連接。
from functools import wraps import tracemalloc from time import perf_counter def measure_performance(func): '''Measure performance of a function''' @wraps(func) def wrapper(*args, **kwargs): tracemalloc.start() start_time = perf_counter() func(*args, **kwargs) current, peak = tracemalloc.get_traced_memory() finish_time = perf_counter() print(f'Function: {func.__name__}') print(f'Method: {func.__doc__}') print(f'Memory usage:\t\t {current / 10**6:.6f} MB \n' f'Peak memory usage:\t {peak / 10**6:.6f} MB ') print(f'Time elapsed is seconds: {finish_time - start_time:.6f}') print(f'{"-"*40}') tracemalloc.stop() return wrapper @measure_performance def make_list1(): '''Range''' my_list = list(range(100000)) @measure_performance def make_list2(): '''List comprehension''' my_list = [l for l in range(100000)] @measure_performance def make_list3(): '''Append''' my_list = [] for item in range(100000): my_list.append(item) @measure_performance def make_list4(): '''Concatenation''' my_list = [] for item in range(100000): my_list = my_list + [item] print(make_list1()) print(make_list2()) print(make_list3()) print(make_list4()) # Output Function: make_list1 Method: Range Memory usage: 0.000072 MB Peak memory usage: 3.693040 MB Time elapsed is seconds: 0.049359 ---------------------------------------- Function: make_list2 Method: List comprehension Memory usage: 0.000856 MB Peak memory usage: 3.618244 MB Time elapsed is seconds: 0.052338 ---------------------------------------- Function: make_list3 Method: Append Memory usage: 0.000448 MB Peak memory usage: 3.617692 MB Time elapsed is seconds: 0.060719 ---------------------------------------- Function: make_list4 Method: Concatenation Memory usage: 0.000440 MB Peak memory usage: 4.393292 MB Time elapsed is seconds: 61.649138 ----------------------------------------
您也可以將裝飾器與類一起使用。讓我們看看如何在 Python 類中使用裝飾器。
在這個例子中,注意沒有@涉及任何字符。使用該__call__方法,在創(chuàng)建類的實(shí)例時執(zhí)行裝飾器。
此類跟蹤查詢 API 的函數(shù)已運(yùn)行的次數(shù)。一旦達(dá)到限制,裝飾器就會停止執(zhí)行該函數(shù)。
import requests class LimitQuery: def __init__(self, func): self.func = func self.count = 0 def __call__(self, *args, **kwargs): self.limit = args[0] if self.count < self.limit: self.count += 1 return self.func(*args, **kwargs) else: print(f'No queries left. All {self.count} queries used.') return @LimitQuery def get_coin_price(limit): '''View the Bitcoin Price Index (BPI)''' url = requests.get('https://api.coindesk.com/v1/bpi/currentprice.json') if url.status_code == 200: text = url.json() return f"${float(text['bpi']['USD']['rate_float']):.2f}" print(get_coin_price(5)) print(get_coin_price(5)) print(get_coin_price(5)) print(get_coin_price(5)) print(get_coin_price(5)) print(get_coin_price(5)) # Output $35968.25 $35896.55 $34368.14 $35962.27 $34058.26 No queries left. All 5 queries used.
這個類將跟蹤類的狀態(tài)。
讀到這里,這篇“怎么創(chuàng)建和使用Python裝飾器”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點(diǎn)還需要大家自己動手實(shí)踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。