歡迎來到我們的系列博客《Python全景系列》第九篇!在這個系列中,我們將帶領你從Python的基礎知識開始,一步步深入到高級話題,幫助你掌握這門強大而靈活的編程語法,無論你是編程新手,還是有一定基礎的開發者,這個系列都將提供你需要的知識和技能,
** 裝飾器在 Python 中扮演了重要的角色,這是一種精巧的語言特性,讓我們能夠修改或增強函式和類的行為,無需修改它們的源代碼,這篇文章將深入探討裝飾器的所有相關主題,包括裝飾器的基礎知識、實作與使用、作業原理,以及通過實際例子學習裝飾器的獨特用法,**
Python 裝飾器深入探討
在 Python 中,裝飾器提供了一種簡潔的方式,用來修改或增強函式和類的行為,裝飾器在語法上表現為一個前置于函式或類定義之前的特殊標記:
@simple_decorator
def hello_world():
print("Hello, world!")
在這個例子中,simple_decorator 是一個裝飾器,它作用于下方的 hello_world 函式,裝飾器在概念上就像一個包裝器,它可以在被裝飾的函式執行前后插入任意的代碼,進而改變被裝飾函式的行為,
引數化裝飾器
我們還可以進一步將裝飾器引數化,這讓裝飾器的行為更具靈活性,比如,我們可以定義一個裝飾器,讓它在函式執行前后列印自定義的訊息:
def message_decorator(before_message, after_message):
def decorator(func):
def wrapper(*args, **kwargs):
print(before_message)
result = func(*args, **kwargs)
print(after_message)
return result
return wrapper
return decorator
@message_decorator("Start", "End")
def hello_world():
print("Hello, world!")
在這個例子中,message_decorator 是一個引數化裝飾器,它接受兩個引數,分別代表函式執行前后要列印的訊息,
理解裝飾器的作業原理
在 Python 中,函式是第一類物件,這意味著函式和其他物件一樣,可以作為變數進行賦值,可以作為引數傳給其他函式,可以作為其他函式的回傳值,甚至可以在一個函式里面定義另一個函式,這個特性是實作裝飾器的基礎,
def decorator(func):
def wrapper():
print('Before function execution')
func()
print('After function execution')
return wrapper
def hello_world():
print('Hello, world!')
decorated_hello = decorator(hello_world)
decorated_hello()
在這個例子中,decorator 函式接收一個函式 hello_world 作為引數,并回傳了一個新的函式 wrapped_func,這個新函式在 hello_world 函式執行前后分別列印一條訊息,我們可以看到,裝飾器實際上是一個回傳函式的函式,
函式簽名保持
默認情況下,裝飾器會“掩蓋”掉原函式的名字和檔案字串,這是因為在裝飾器內部,我們回傳了一個全新的函式,我們可以使用 functools.wraps 來解決這個問題:
import functools
def decorator(func):
@functools.wraps(func)
def wrapper():
print('Before function execution')
func()
print('After function execution')
return wrapper
@decorator
def hello_world():
"Prints 'Hello, world!'"
print('Hello, world!')
print(hello_world.__name__)
print(hello_world.__doc__)
這樣,使用裝飾器后的函式名和檔案字串能夠保持不變,
Python 裝飾器的應用實體
裝飾器在實際的 Python 編程中有許多應用場景,比如日志記錄、性能測驗、事務處理、快取、權限校驗等,
一個常見的應用就是使用裝飾器進行日志記錄:
import logging
def log_decorator(func):
logging.basicConfig(level=logging.INFO)
def wrapper(*args, **kwargs):
logging.info(f'Running "{func.__name__}" with arguments {args} and kwargs {kwargs}')
result = func(*args, **kwargs)
logging.info(f'Finished "{func.__name__}" with result {result}')
return result
return wrapper
@log_decorator
def add(x, y):
return x + y
這個裝飾器記錄了函式的名稱,函式呼叫的引數,以及函式回傳的結果,
裝飾器鏈
Python 允許我們將多個裝飾器應用到一個函式上,形成一個裝飾器鏈,例如,我們可以同時應用日志裝飾器和性能測驗裝飾器:
import time
import logging
from functools import wraps
def log_decorator(func):
logging.basicConfig(level=logging.INFO)
@wraps(func)
def wrapper(*args, **kwargs):
logging.info(f'Running "{func.__name__}" with arguments {args} and kwargs {kwargs}')
result = func(*args, **kwargs)
logging.info(f'Finished "{func.__name__}" with result {result}')
return result
return wrapper
def timer_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f'Function "{func.__name__}" took {end_time - start_time} seconds to run.')
return result
return wrapper
@log_decorator
@timer_decorator
def add(x, y):
time.sleep(2)
return x + y
在這個例子中,@log_decorator 和 @timer_decorator 兩個裝飾器被同時應用到 add 函式上,它們分別負責記錄日志和測量函式運行時間,
One More Thing: 自動注冊裝飾器
一個有趣的裝飾器應用是自動注冊,這個裝飾器會在裝飾函式時自動將函式添加到一個串列或字典中,這樣我們就可以在程式的其他地方訪問到這個串列或字典,知道有哪些函式被裝飾過,
# 裝飾器將函式注冊到一個串列中
def register_decorator(func_list):
def decorator(func):
func_list.append(func)
return func
return decorator
# 自動注冊函式
registered_functions = []
@register_decorator(registered_functions)
def foo():
pass
@register_decorator(registered_functions)
def bar():
pass
print(registered_functions) # 輸出: [<function foo at 0x10d38d160>, <function bar at 0x10d38d1f0>]
這個裝飾器可以用于自動注冊路由、插件系統、命令列引數處理等場景,能夠大大提高代碼的靈活性和可擴展性,
總結
Python 裝飾器是一種強大的工具,它可以讓我們更有效地管理和組織代碼,希望通過這篇文章,你能夠更深入地理解裝飾器的作業原理和用法,從而在你的專案中更好地使用裝飾器,
如有幫助,請多關注
個人微信公眾號:【Python全視角】
TeahLead_KrisChang,10+年的互聯網和人工智能從業經驗,10年+技術和業務團隊管理經驗,同濟軟體工程本科,復旦工程管理碩士,阿里云認證云服務資深架構師,上億營收AI產品業務負責人,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/553941.html
標籤:Python
上一篇:Java中序列化和反序列化解釋
下一篇:返回列表
