搜尋
首頁後端開發Python教學附參數的全型 Python 裝飾器

附參數的全型 Python 裝飾器

這篇短文中顯示的程式碼取自我的小型開源專案按合約設計,它提供了一個類型化的裝飾器。裝飾器是一個非常有用的概念,你肯定會在網路上找到很多關於它們的介紹。簡單說,它們允許在每次調用裝飾函數時(之前和之後)執行程式碼。透過這種方式,你可以修改函數參數或傳回值、測量執行時間、新增日誌記錄、執行執行時類型檢查等等。請注意,裝飾器也可以為類別編寫,提供另一種元程式設計方法(例如在attrs 套件中完成)

#在最簡單的形式中,裝飾器的定義類似於以下程式碼:

def my_first_decorator(func):
 def wrapped(*args, **kwargs):
 # do something before
 result = func(*args, **kwargs)
 # do something after
 return result
 return wrapped
@my_first_decorator
def func(a):
 return a

如上程式碼,因為當定義了被包裝的巢狀函數時,它的周圍變數可以在函數內存取並保存在記憶體中,只要該函數在某處使用(這在函數式程式語言中稱為閉包)。

很簡單, 但這有一些缺點。最大的問題是修飾函數會丟失它的之前的函數名字(你可以用inspect.signature看到這個),它的文檔字符串,甚至它的名字, 這些是源代碼文檔工具(例如sphinx)的問題,但可以使用標準庫中的functools.wraps 裝飾器輕鬆解決:

from functools import wraps
from typing import Any, Callable, TypeVar, ParamSpec
P = ParamSpec("P") # 需要python >= 3.10
R = TypeVar("R")
def my_second_decorator(func: Callable[P, R]) -> Callable[P, R]:
 @wraps(func)
 def wrapped(*args: Any, **kwargs: Any) -> R:
 # do something before
 result = func(*args, **kwargs)
 # do something after
 return result
 return wrapped
@my_second_decorator
def func2(a: int) -> int:
 """Does nothing"""
 return a
print(func2.__name__)
# 'func2'
print(func2.__doc__)
# 'Does nothing'

在這個例子中,我已經添加了類型註釋,註釋和類型提示是對Python 所做的最重要的補充。更好的可讀性、IDE 中的程式碼完成以及更大程式碼庫的可維護性只是其中的幾個例子。上面的程式碼應該已經涵蓋了大多數用例,但無法參數化裝飾器。考慮編寫一個裝飾器來記錄函數的執行時間,但前提是它超過了一定的秒數。這個數量應該可以為每個裝飾函數單獨配置。如果沒有指定,則應使用預設值,並且應使用不含括號的裝飾器,以便更容易使用:

@time(threshold=2)
def func1(a):
...
# No paranthesis when using default threshold
@time
def func2(b):
...

如果你可以在第二種情況下使用括號,或者根本不提供參數的預設值,那麼這個秘訣就足夠了:

from functools import wraps
from typing import Any, Callable, TypeVar, ParamSpec
P = ParamSpec("P") # 需要python >= 3.10
R = TypeVar("R")
def my_third_decorator(threshold: int = 1) -> Callable[[Callable[P, R]], Callable[P, R]]:
 def decorator(func: Callable[P, R]) -> Callable[P, R]:
 @wraps(func)
 def wrapper(*args: Any, **kwargs: Any) -> R:
 # do something before you can use `threshold`
 result = func(*args, **kwargs)
 # do something after
 return result
 return wrapper
 return decorator
@my_third_decorator(threshold=2)
def func3a(a: int) -> None:
...
# works
@my_third_decorator()
def func3b(a: int) -> None:
...
# Does not work!
@my_third_decorator
def func3c(a: int) -> None:
...

為了涵蓋第三種情況,有一些包,即wraps 和decorator,它們實際上可以做的不僅僅是添加可選參數。雖然質量非常高,但它們引入了相當多的額外複雜性。使用 wrapt-decorated 函數,在遠端叢集上運行函數時,我進一步遇到了序列化問題。據我所知,兩者都沒有完全鍵入,因此靜態類型檢查器/ linter(例如 mypy)在嚴格模式下失敗。

當我在自己的套件上工作並決定編寫自己的解決方案時,必須解決這些問題。它變成了一種可以輕鬆重複使用但很難轉換為庫的模式。

它使用標準函式庫的重載裝飾器。這樣,可以指定相同的裝飾器與我們的無參數一起使用。除此之外,它是上面兩個片段的組合。這種方法的一個缺點是所有參數都需要作為關鍵字參數給出(畢竟增加了可讀性)

from typing import Callable, TypeVar, ParamSpec
from functools import partial, wraps
P = ParamSpec("P") # requires python >= 3.10
R = TypeVar("R
@overload
def typed_decorator(func: Callable[P, R]) -> Callable[P, R]:
...
@overload
def typed_decorator(*, first: str = "x", second: bool = True) -> Callable[[Callable[P, R]], Callable[P, R]]:
...
def typed_decorator(
 func: Optional[Callable[P, R]] = None, *, first: str = "x", second: bool = True
) -> Union[Callable[[Callable[P, R]], Callable[P, R]], Callable[P, R]]:
 """
Describe what the decorator is supposed to do!
Parameters
----------
first : str, optional
First argument, by default "x".
This is a keyword-only argument!
second : bool, optional
Second argument, by default True.
This is a keyword-only argument!
"""
 def wrapper(func: Callable[P, R], *args: Any, **kw: Any) -> R:
 """The actual logic"""
 # Do something with first and second and produce a `result` of type `R`
 return result
 # Without arguments `func` is passed directly to the decorator
 if func is not None:
 if not callable(func):
 raise TypeError("Not a callable. Did you use a non-keyword argument?")
 return wraps(func)(partial(wrapper, func))
 # With arguments, we need to return a function that accepts the function
 def decorator(func: Callable[P, R]) -> Callable[P, R]:
 return wraps(func)(partial(wrapper, func))
 return decorator

稍後,我們可以分別使用我們的不帶參數的裝飾器

@typed_decorator
def spam(a: int) -> int:
 return a
@typed_decorator(first = "y
def eggs(a: int) -> int:
 return a

這種模式肯定有一些開銷,但收益大於成本。

原文:https://www.php.cn/link/d0f82e1046ccbd597c7f2a7bfba9e7dd

#

以上是附參數的全型 Python 裝飾器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:51CTO.COM。如有侵權,請聯絡admin@php.cn刪除
Python:探索其主要應用程序Python:探索其主要應用程序Apr 10, 2025 am 09:41 AM

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

您可以在2小時內學到多少python?您可以在2小時內學到多少python?Apr 09, 2025 pm 04:33 PM

兩小時內可以學到Python的基礎知識。 1.學習變量和數據類型,2.掌握控制結構如if語句和循環,3.了解函數的定義和使用。這些將幫助你開始編寫簡單的Python程序。

如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎?如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎?Apr 02, 2025 am 07:18 AM

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到?如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到?Apr 02, 2025 am 07:15 AM

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

Python 3.6加載Pickle文件報錯"__builtin__"模塊未找到怎麼辦?Python 3.6加載Pickle文件報錯"__builtin__"模塊未找到怎麼辦?Apr 02, 2025 am 07:12 AM

Python3.6環境下加載Pickle文件報錯:ModuleNotFoundError:Nomodulenamed...

如何提高jieba分詞在景區評論分析中的準確性?如何提高jieba分詞在景區評論分析中的準確性?Apr 02, 2025 am 07:09 AM

如何解決jieba分詞在景區評論分析中的問題?當我們在進行景區評論分析時,往往會使用jieba分詞工具來處理文�...

如何使用正則表達式匹配到第一個閉合標籤就停止?如何使用正則表達式匹配到第一個閉合標籤就停止?Apr 02, 2025 am 07:06 AM

如何使用正則表達式匹配到第一個閉合標籤就停止?在處理HTML或其他標記語言時,常常需要使用正則表達式來�...

如何繞過Investing.com的反爬蟲機制獲取新聞數據?如何繞過Investing.com的反爬蟲機制獲取新聞數據?Apr 02, 2025 am 07:03 AM

攻克Investing.com的反爬蟲策略許多人嘗試爬取Investing.com(https://cn.investing.com/news/latest-news)的新聞數據時,常常�...

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器