ホームページ > バックエンド開発 > Python チュートリアル > よりクリーンで効率的なコードのための重要な Python デコレータ パターン

よりクリーンで効率的なコードのための重要な Python デコレータ パターン

Linda Hamilton
リリース: 2025-01-04 03:25:39
オリジナル
724 人が閲覧しました

ssential Python Decorator Patterns for Cleaner, More Efficient Code

ベストセラー作家として、アマゾンで私の本を探索することをお勧めします。 Medium で私をフォローしてサポートを示すことを忘れないでください。ありがとう!あなたのサポートは世界を意味します!

Python デコレータは、コア ロジックを変更せずに関数やクラスを変更または拡張できる強力な機能です。開発者として、デコレータ パターンをマスターすると、コードの品質、再利用性、保守性が大幅に向上することがわかりました。私のプロジェクトで特に便利だと感じた 7 つの重要なデコレータ パターンを見てみましょう。

クラスデコレーター

クラス デコレータは、クラスの動作と属性を変更または強化する方法を提供します。これらは、クラス定義のすぐ上の @decorator 構文を使用して適用されます。私は、メソッドの追加、既存のメソッドの変更、クラス属性の変更にクラス デコレータをよく使用してきました。

これは、クラスに新しいメソッドを追加するクラス デコレーターの例です。

def add_greeting(cls):
    def say_hello(self):
        return f"Hello, I'm {self.name}"
    cls.say_hello = say_hello
    return cls

@add_greeting
class Person:
    def __init__(self, name):
        self.name = name

person = Person("Alice")
print(person.say_hello())  # Output: Hello, I'm Alice
ログイン後にコピー
ログイン後にコピー

この例では、add_greeting デコレーターは、say_hello メソッドを Person クラスに追加します。このパターンは、ソース コードを変更せずに複数のクラスにわたって機能を拡張したい場合に特に便利です。

引数を持つ関数デコレータ

引数を受け入れる関数デコレータを使用すると、さらに柔軟性が高まります。これらを使用すると、デコレーター自体の動作をカスタマイズできます。さまざまなユースケースに合わせて微調整できる再利用可能なデコレータを作成する場合、このパターンが非常に貴重であることがわかりました。

これは、指定された回数だけ関数呼び出しを繰り返すことができるデコレータの例です:

def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(times=3)
def greet(name):
    print(f"Hello, {name}!")

greet("Bob")
# Output:
# Hello, Bob!
# Hello, Bob!
# Hello, Bob!
ログイン後にコピー
ログイン後にコピー

この例では、repeat デコレータは、装飾された関数を何回呼び出すかを決定する引数を受け取ります。このパターンにより、デコレータを関数に適用する方法に大きな柔軟性が与えられます。

関数メタデータの保存

デコレーターを使用する場合、元の関数のメタデータを保持することが重要です。これには、関数の名前、docstring、およびその他の属性が含まれます。 Python 標準ライブラリの functools.wraps デコレータは、これを実現するのに役立ちます。

これが例です:

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """This is the wrapper function"""
        print("Something is happening before the function is called.")
        result = func(*args, **kwargs)
        print("Something is happening after the function is called.")
        return result
    return wrapper

@my_decorator
def say_hello(name):
    """This function greets someone"""
    print(f"Hello, {name}!")

say_hello("Charlie")
print(say_hello.__name__)  # Output: say_hello
print(say_hello.__doc__)   # Output: This function greets someone
ログイン後にコピー
ログイン後にコピー

@wraps(func) を使用することで、ラッパー関数が元の関数のメタデータを確実に引き継ぐことができます。これはデバッグとイントロスペクションにとって非常に重要です。

複数のデコレータを積み重ねる

デコレータはスタックできるため、複数のデコレータを 1 つの関数に適用できます。装飾の順序は重要であり、デコレータは下から上に適用されます。

これが例です:

def decorator1(func):
    def wrapper(*args, **kwargs):
        print("Decorator 1")
        return func(*args, **kwargs)
    return wrapper

def decorator2(func):
    def wrapper(*args, **kwargs):
        print("Decorator 2")
        return func(*args, **kwargs)
    return wrapper

@decorator1
@decorator2
def greet(name):
    print(f"Hello, {name}!")

greet("David")
# Output:
# Decorator 1
# Decorator 2
# Hello, David!
ログイン後にコピー
ログイン後にコピー

この例では、decorator2 が最初に適用され、次にdecorator1 が適用されます。複数のデコレータを使用する場合、実行順序を理解することが重要です。

メモ化デコレーター

メモ化は、負荷の高い関数呼び出しの結果を保存し、同じ入力が再度発生したときにキャッシュされた結果を返す最適化手法です。メモ化デコレーターは、再帰関数や高価な計算を伴う関数のパフォーマンスを向上させるのに非常に便利であることがわかりました。

メモ化デコレータの例を次に示します:

def add_greeting(cls):
    def say_hello(self):
        return f"Hello, I'm {self.name}"
    cls.say_hello = say_hello
    return cls

@add_greeting
class Person:
    def __init__(self, name):
        self.name = name

person = Person("Alice")
print(person.say_hello())  # Output: Hello, I'm Alice
ログイン後にコピー
ログイン後にコピー

このメモ化デコレーターはフィボナッチ関数の結果をキャッシュし、大規模な入力に対するパフォーマンスを劇的に向上させます。

タイミングおよびロギングデコレーター

関数実行のタイミングと関数呼び出しのログを記録するためのデコレーターは、パフォーマンス分析とデバッグに非常に役立ちます。私は開発プロセスでこれらを頻繁に使用します。

これは、タイミングとロギングのデコレーターを組み合わせた例です。

def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(times=3)
def greet(name):
    print(f"Hello, {name}!")

greet("Bob")
# Output:
# Hello, Bob!
# Hello, Bob!
# Hello, Bob!
ログイン後にコピー
ログイン後にコピー

このデコレーターは、関数が呼び出されたときと実行にかかる時間をログに記録します。これは、コード内のパフォーマンスのボトルネックを特定するのに非常に貴重なパターンです。

コンテキストマネージャーデコレーター

コンテキスト マネージャーは通常、リソース管理とエラー処理のために with ステートメントとともに使用されます。関数をコンテキスト マネージャーに変えるデコレーターを作成して、エレガントなセットアップと破棄操作を可能にすることができます。

これが例です:

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """This is the wrapper function"""
        print("Something is happening before the function is called.")
        result = func(*args, **kwargs)
        print("Something is happening after the function is called.")
        return result
    return wrapper

@my_decorator
def say_hello(name):
    """This function greets someone"""
    print(f"Hello, {name}!")

say_hello("Charlie")
print(say_hello.__name__)  # Output: say_hello
print(say_hello.__doc__)   # Output: This function greets someone
ログイン後にコピー
ログイン後にコピー

この例では、file_manager デコレーターは、例外が発生した場合でも、操作後にファイルが適切に閉じられるようにします。

デコレータの作成と使用のベスト プラクティス

デコレーターと協力するときに、私に役立ついくつかのベスト プラクティスを学びました。

  1. 関数のメタデータを保存するには、functools.wraps を使用します。
  2. デコレータはシンプルにして、単一の責任に集中してください。
  3. デコレータに引数を渡す必要がある場合は、デコレータ ファクトリを使用します。
  4. 特に頻繁に呼び出される関数については、デコレータのパフォーマンスへの影響に注意してください。
  5. デコレータを明確に文書化し、デコレータの動作とその副作用を説明します。
  6. デバッグするときは、デコレーターが間接層を追加することに注意してください。 Python デバッガーの @ 構文などのツールは、装飾された関数にステップインするのに役立ちます。

装飾されたコードのテストは難しい場合があります。私がよく使用するアプローチの 1 つは、デコレーターを装飾された関数とは別にテストすることです。これにより、より詳細なテストが可能になり、デバッグが容易になります。

デコレーターをテストする方法の例を次に示します。

def decorator1(func):
    def wrapper(*args, **kwargs):
        print("Decorator 1")
        return func(*args, **kwargs)
    return wrapper

def decorator2(func):
    def wrapper(*args, **kwargs):
        print("Decorator 2")
        return func(*args, **kwargs)
    return wrapper

@decorator1
@decorator2
def greet(name):
    print(f"Hello, {name}!")

greet("David")
# Output:
# Decorator 1
# Decorator 2
# Hello, David!
ログイン後にコピー
ログイン後にコピー

このテストでは、モック関数を使用して、デコレータが元の関数を正しく呼び出し、その結果を返しているかどうかを確認します。

デコレーターは Python の強力なツールであり、これらのパターンをマスターすると、コーディングの武器を大幅に強化できます。これらにより、懸念事項の明確な分離が可能になり、コードの再利用が促進され、コードがより読みやすく保守しやすくなります。

デコレーターを効果的に使用するための鍵は、単純なものから始めて、必要に応じて徐々に複雑さを増していくことであることがわかりました。基本的な関数デコレータから始めて、クラス デコレータやデコレータ ファクトリなどのより高度なパターンに進みます。

デコレーターはコードを大幅に改善できますが、慎重に使用する必要があることに注意してください。デコレータを過度に使用すると、理解やデバッグが困難なコードになる可能性があります。デコレータが特定のユースケースにとって最適なソリューションであるかどうかを常に検討してください。

デコレーターとの作業を続けると、新しいパターンや使用例を発見する可能性があります。 Python コミュニティは常に革新を続けており、新しいデコレータ テクニックが定期的に登場します。好奇心を持ち、さまざまなアプローチを試し、プロジェクト固有の問題を解決するために独自のデコレーター パターンを遠慮なく作成してください。

デコレータは、よりクリーンで効率的なコードを作成するのに役立つ Python の多くの強力な機能の 1 つにすぎません。デコレーターに慣れてくると、デコレーターがジェネレーター、コンテキスト マネージャー、メタクラスなどの他の Python 機能とうまく統合され、エレガントで強力なコード設計の可能性がさらに広がることがわかります。


101冊

101 Books は、著者 Aarav Joshi が共同設立した AI 主導の出版社です。高度な AI テクノロジーを活用することで、出版コストを信じられないほど低く抑えており、書籍によっては $4 という低価格で販売されており、誰もが質の高い知識にアクセスできるようになっています。

Amazon で入手できる私たちの書籍 Golang Clean Code をチェックしてください。

最新情報とエキサイティングなニュースにご期待ください。本を購入する際は、Aarav Joshi を検索して、さらに多くのタイトルを見つけてください。提供されたリンクを使用して特別割引をお楽しみください!

私たちの作品

私たちの作品をぜひチェックしてください:

インベスターセントラル | 投資家中央スペイン人 | 中央ドイツの投資家 | スマートな暮らし | エポックとエコー | 不可解な謎 | ヒンドゥーヴァ | エリート開発者 | JS スクール


私たちは中程度です

Tech Koala Insights | エポックズ&エコーズワールド | インベスター・セントラル・メディア | 不可解な謎 中 | 科学とエポックミディアム | 現代ヒンドゥーヴァ

以上がよりクリーンで効率的なコードのための重要な Python デコレータ パターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート