検索
ホームページバックエンド開発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):
...

2 番目のケースで括弧を使用できる場合、または指定しないでください。パラメータのデフォルト値がまったくない場合は、このレシピで十分です:

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:
...

3 番目のケースをカバーするには、使用可能な Select パラメータを追加するだけでなく、実際にはそれ以上のことを実行できるパッケージ、つまりラップとデコレータがあります。品質は非常に高いですが、かなりの複雑さが追加されます。 Wrapt で装飾された関数を使用すると、リモート クラスターで関数を実行するときにシリアル化の問題がさらに発生しました。私の知る限り、どちらも完全に型指定されていないため、静的型チェッカー/リンター (mypy など) は厳密モードでは失敗します。

私が独自のパッケージに取り組み、独自のソリューションを作成することにしたとき、これらの問題を解決する必要がありました。再利用はしやすいがライブラリ化が難しいパターンとなります。

標準ライブラリのオーバーロードされたデコレータを使用します。このようにして、同じデコレータをパラメータのないデコレータで使用するように指定できます。それ以外は、上記の 2 つのスニペットを組み合わせたものです。このアプローチの欠点の 1 つは、すべてのパラメーターをキーワード引数として指定する必要があることです (これにより、最終的に読みやすさが向上します)

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 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事は51CTO.COMで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
Pythonアレイで実行できる一般的な操作は何ですか?Pythonアレイで実行できる一般的な操作は何ですか?Apr 26, 2025 am 12:22 AM

PythonArraysSupportVariousoperations:1)SlicingExtractsSubsets、2)Appending/ExtendingAdddesements、3)inSertingSelementSatspecificpositions、4)remvingingDeletesements、5)sorting/verversingsorder、and6)listenionsionsionsionsionscreatenewlistsebasedexistin

一般的に使用されているnumpy配列はどのようなアプリケーションにありますか?一般的に使用されているnumpy配列はどのようなアプリケーションにありますか?Apr 26, 2025 am 12:13 AM

numpyarraysAressertialentionsionceivationsefirication-efficientnumericalcomputations andDatamanipulation.theyarecrucialindatascience、mashineelearning、物理学、エンジニアリング、および促進可能性への適用性、scaledatiencyを効率的に、forexample、infinancialanalyyy

Pythonのリスト上の配列を使用するのはいつですか?Pythonのリスト上の配列を使用するのはいつですか?Apr 26, 2025 am 12:12 AM

UseanArray.ArrayOverAlistinPythonは、Performance-criticalCode.1)homogeneousdata:araysavememorywithpedelements.2)Performance-criticalcode:Araysofterbetterbetterfornumerumerumericaleperations.3)interf

すべてのリスト操作は配列でサポートされていますか?なぜまたはなぜですか?すべてのリスト操作は配列でサポートされていますか?なぜまたはなぜですか?Apr 26, 2025 am 12:05 AM

いいえ、notallistoperationSaresuptedbyarrays、andviceversa.1)arraysdonotsupportdynamicoperationslikeappendorintorintorinsertizizing、whosimpactsporformance.2)リスト

Pythonリストの要素にどのようにアクセスしますか?Pythonリストの要素にどのようにアクセスしますか?Apr 26, 2025 am 12:03 AM

toaccesselementsinapythonlist、useindexing、negativeindexing、slicing、oriteration.1)indexingstartsat0.2)negativeindexingAcsesess.3)slicingextractStions.4)reterationSuseSuseSuseSuseSeSeS forLoopseCheckLentlentlentlentlentlentlenttodExeror。

Pythonを使用した科学コンピューティングでアレイはどのように使用されていますか?Pythonを使用した科学コンピューティングでアレイはどのように使用されていますか?Apr 25, 2025 am 12:28 AM

Arraysinpython、特にvianumpy、arecrucialinscientificComputing fortheirefficienty andversitility.1)彼らは、fornumericaloperations、data analysis、andmachinelearning.2)numpy'simplementation incensuresfasteroperationsthanpasteroperations.3)arayableminablecickick

同じシステムで異なるPythonバージョンをどのように処理しますか?同じシステムで異なるPythonバージョンをどのように処理しますか?Apr 25, 2025 am 12:24 AM

Pyenv、Venv、およびAnacondaを使用して、さまざまなPythonバージョンを管理できます。 1)Pyenvを使用して、複数のPythonバージョンを管理します。Pyenvをインストールし、グローバルバージョンとローカルバージョンを設定します。 2)VENVを使用して仮想環境を作成して、プロジェクトの依存関係を分離します。 3)Anacondaを使用して、データサイエンスプロジェクトでPythonバージョンを管理します。 4)システムレベルのタスク用にシステムPythonを保持します。これらのツールと戦略を通じて、Pythonのさまざまなバージョンを効果的に管理して、プロジェクトのスムーズな実行を確保できます。

標準のPythonアレイでnumpyアレイを使用することの利点は何ですか?標準のPythonアレイでnumpyアレイを使用することの利点は何ですか?Apr 25, 2025 am 12:21 AM

numpyarrayshaveveraladvantages-averstandardpythonarrays:1)thealmuchfasterduetocベースのインプレンテーション、2)アレモレメモリ効率、特にlargedatasets、および3)それらは、拡散化された、構造化された形成術科療法、

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター