テクノロジー 開発 非公開: Python デコレーター: 説明 (例と使用例付き)

Python デコレーター: 説明 (例と使用例付き)

Python デコレータは、Python の非常に便利な構造です。 Python でデコレータを使用すると、関数を別の関数内にラップすることで関数の動作を変更できます。デコレータを使用すると、よりクリーンなコードを記述し、機能を共有できるようになります。この記事では、デコレータの使用方法だけでなく、デコレータの作成方法についても説明します。

前提知識

Python のデコレータのトピックには、ある程度の背景知識が必要です。以下に、このチュートリアルを理解するためにすでに理解しておく必要があるいくつかの概念をリストします。必要に応じて概念をブラッシュアップできるリソースへのリンクもあります。

基本的な Python

このトピックは、より中級/上級のトピックです。そのため、学習を始める前に、データ型、関数、オブジェクト、クラスなどの Python の基本をすでに理解している必要があります。

また、ゲッター、セッター、コンストラクターなどのオブジェクト指向の概念も理解する必要があります。 Python プログラミング言語に詳しくない場合は、始めるためのリソースをいくつか紹介します。

職務は第一級市民である

基本的な Python に加えて、Python のより高度な概念についても知っておく必要があります。関数、および Python の他のほとんどすべてのものは、 int string のようなオブジェクトです。これらはオブジェクトであるため、次のようないくつかの操作を行うことができます。

  • string または int 関数の引数として渡すのと同じ方法で、関数を引数として別の関数に渡すことができます。
  • 他の string または int 値を返す場合と同様に、他の関数によって関数を返すこともできます。
  • 関数は変数に格納できる

実際、関数オブジェクトと他のオブジェクトの唯一の違いは、関数オブジェクトにはマジック メソッド __call__() が含まれていることです。

この時点で、前提条件となる知識を理解していただければ幸いです。主要なトピックについて議論を始めましょう。

Python デコレータとは何ですか?

Python デコレーターは、単に関数を引数として取り込み、渡された関数の修正バージョンを返す関数です。言い換えると、関数 foo が引数として関数 bar を取り込む場合、関数 foo はデコレーターになります。そして別の関数 baz を返します。

関数 baz baz の本体内で関数 bar への呼び出しがあるという意味で、 bar を変更したものです。ただし、 bar の呼び出しの前後では、 baz 何でもできます。それは一口でした。状況を説明するコードを次に示します。

 # Foo is a decorator, it takes in another function, bar as an argument
def foo(bar):

    # Here we create baz, a modified version of bar
    # baz will call bar but can do anything before and after the function call
    def baz():

        # Before calling bar, we print something
        print("Something")

        # Then we run bar by making a function call
        bar()

        # Then we print something else after running bar
        print("Something else")

    # Lastly, foo returns baz, a modified version of bar
    return baz

Python でデコレータを作成するには?

Python でデコレーターがどのように作成され、使用されるかを説明するために、簡単な例で説明します。この例では、関数が実行されるたびに、装飾している関数の名前をログに記録するロガー デコレーター関数を作成します。

まず、デコレータ関数を作成しました。デコレータは引数として func を受け取ります。 func は装飾している関数です。

 def create_logger(func):
    # The function body goes here

デコレーター関数内で、 func を実行する前に func の名前をログに記録する変更された関数を作成します。

 # Inside create_logger
def modified_func():
    print("Calling: ", func.__name__)
    func()

次に、 create_logger 関数は変更された関数を返します。その結果、 create_logger 関数全体は次のようになります。

 def create_logger(func):
    def modified_func():
        print("Calling: ", func.__name__)
        func()

    return modified_function

デコレータの作成が完了しました。 create_logger 関数は、デコレータ関数の簡単な例です。これは、装飾している関数である func を受け取り、別の関数 modified_func を返します。 modified_func func を実行する前に、まず func の名前をログに記録します。

Python でデコレータを使用する方法

デコレーターを使用するには、次のように @ 構文を使用します。

 @create_logger
def say_hello():
    print("Hello, World!")

これで、スクリプト内でsay_hello()を呼び出すことができ、出力は次のテキストになるはずです。

 Calling:  say_hello
"Hello, World" 
Python デコレータを使用するプログラムのスクリーンショット
Python デコレータを使用するプログラムのスクリーンショット

しかし、 @create_ create_logger は何をしているのでしょうか?そうですね、say_hello 関数にデコレータを適用しています。何をしているのかをよりよく理解するために、この段落のすぐ下のコードは、 say_hello の前に @create_logger を置くのと同じ結果を達成します。

 def say_hello():
    print("Hello, World!")

say_hello = create_logger(say_hello)

つまり、Python でデコレータを使用する 1 つの方法は、上記のコードで行ったように、関数を渡してデコレータを明示的に呼び出すことです。もう 1 つのより簡潔な方法は、 @ 構文を使用することです。

このセクションでは、Python デコレータの作成方法について説明しました。

もう少し複雑な例

上記の例は単純なケースでした。装飾している関数が引数を受け取る場合など、もう少し複雑な例があります。もう 1 つのより複雑な状況は、クラス全体を装飾したい場合です。ここではこれら両方の状況について説明します。

関数が引数を受け取るとき

デコレートしている関数が引数を受け取る場合、変更された関数は引数を受け取り、最終的に未変更の関数を呼び出すときにそれらを渡す必要があります。わかりにくいと思われる場合は、フーバー用語で説明しましょう。

foo はデコレーター関数、 bar は装飾する関数、 baz は装飾された bar であることを思い出してください。その場合、 bar は引数を受け取り、 baz の呼び出し中にそれらを baz に渡します。概念を明確にするためのコード例を次に示します。

 def foo(bar):
    def baz(*args, **kwargs):
        # You can do something here
        ___
        # Then we make the call to bar, passing in args and kwargs
        bar(*args, **kwargs)
        # You can also do something here
        ___

    return baz

*args **kwargs に見慣れない場合は、これらはそれぞれ、位置引数とキーワード引数への単なるポインタです。

baz 引数にアクセスできるため、 bar を呼び出す前に引数の検証を実行できることに注意することが重要です。

例としては、デコレータ関数 ensure_string あり、デコレータ関数に渡される引数が文字列であることを保証する場合が考えられます。次のように実装します。

 def ensure_string(func):
    def decorated_func(text):
        if type(text) is not str:
             raise TypeError('argument to ' + func.__name__ + ' must be a string.')
        else:
             func(text)

    return decorated_func

次のように say_hello 関数を装飾できます。

 @ensure_string
def say_hello(name):
    print('Hello', name)

次に、これを使用してコードをテストできます。

 say_hello('John') # Should run just fine
say_hello(3) # Should throw an exception

そして、次の出力が生成されるはずです。

 Hello John
Traceback (most recent call last):
   File "/home/anesu/Documents/python-tutorial/./decorators.py", line 20, in <module> say hello(3) # should throw an exception
   File "/home/anesu/Documents/python-tu$ ./decorators.pytorial/./decorators.py", line 7, in decorated_func raise TypeError('argument to + func._name_ + must be a string.')
TypeError: argument to say hello must be a string. $0 
2023-05-23-02-33-18 のスクリーンショット
2023-05-23-02-33-18 のスクリーンショット

「John」は文字列であるため、予想どおり、スクリプトは「Hello John」を出力できました。 「Hello 3」を出力しようとすると、「3」が文字列ではないため、例外がスローされました。 ensure_string デコレータは、文字列を必要とする関数の引数を検証するために使用できます。

クラスの飾りつけ

関数を装飾するだけでなく、クラスを装飾することもできます。デコレータをクラスに追加すると、デコレータ メソッドがクラスのコンストラクタ/イニシエーター メソッド (__init__) を置き換えます。

foo-bar に戻ります。foo がデコレータ、Bar が装飾対象のクラスであるとします。その場合、foo は Bar.__init__ を装飾します。これは、 Bar 型のオブジェクトがインスタンス化される前に何かをしたい場合に便利です。

つまり、次のコードは

def foo(func):
    def new_func(*args, **kwargs):
        print('Doing some stuff before instantiation')
        func(*args, **kwargs)

    return new_func

@foo
class Bar:
    def __init__(self):
        print("In initiator")

と同等です

def foo(func):
    def new_func(*args, **kwargs):
        print('Doing some stuff before instantiation')
        func(*args, **kwargs)

    return new_func

class Bar:
    def __init__(self):
        print("In initiator")


Bar.__init__ = foo(Bar.__init__)

実際、2 つのメソッドのいずれかを使用して定義された Bar クラスのオブジェクトをインスタンス化すると、同じ出力が得られます。

 Doing some stuff before instantiation
In initiator 
2023-05-23-02-20-38 のスクリーンショット
2023-05-23-02-20-38 のスクリーンショット

Python のデコレータの例

独自のデコレータを定義できますが、Python にすでに組み込まれているものもあります。 Python で使用される一般的なデコレータの一部を次に示します。

@静的メソッド

静的メソッドは、クラスが装飾しているメソッドが静的メソッドであることを示すためにクラスで使用されます。静的メソッドは、クラスをインスタンス化せずに実行できるメソッドです。次のコード例では、静的メソッド bark を使用してクラス Dog を作成します。

 class Dog:
    @staticmethod
    def bark():
        print('Woof, woof!')

これで、次のように bark メソッドにアクセスできるようになります。

 Dog.bark()

コードを実行すると、次の出力が生成されます。

 Woof, woof! 
2023-05-23-02-02-07 のスクリーンショット
2023-05-23-02-02-07 のスクリーンショット

デコレータの使用方法のセクションで述べたように、デコレータは 2 つの方法で使用できます。 @ 構文は、2 つのうちの 1 つとしてより簡潔です。もう 1 つの方法は、デコレーター関数を呼び出し、装飾したい関数を引数として渡します。つまり、上のコードは以下のコードと同じことを実現します。

 class Dog:
    def bark():
        print('Woof, woof!')

Dog.bark = staticmethod(Dog.bark)

そして、同じ方法で bark メソッドを使用することもできます。

 Dog.bark()

そして、同じ出力が生成されます

Woof, woof! 
2023-05-23-02-02-07-1 のスクリーンショット
2023-05-23-02-02-07-1 のスクリーンショット

ご覧のとおり、最初の方法の方がすっきりしており、コードを読み始める前から関数が静的関数であることがより明らかです。そのため、残りの例では最初の方法を使用します。ただし、2 番目の方法は代替手段であることを覚えておいてください。

@クラスメソッド

このデコレータは、デコレータが装飾しているメソッドがクラス メソッドであることを示すために使用されます。クラス メソッドは、呼び出す前にクラスをインスタンス化する必要がないという点で静的メソッドと似ています。

ただし、主な違いは、クラス メソッドはクラス属性にアクセスできるのに対し、静的メソッドはアクセスできないことです。これは、Python が呼び出されるたびに、そのクラスをクラス メソッドの最初の引数として自動的に渡すためです。 Python でクラス メソッドを作成するには、 classmethod デコレータを使用できます。

 class Dog:
    @classmethod
    def what_are_you(cls):
        print("I am a " + cls.__name__ + "!")

コードを実行するには、クラスをインスタンス化せずにメソッドを呼び出すだけです。

 Dog.what_are_you()

そして出力は次のようになります。

 I am a Dog! 
2023-05-23-02-07-18 のスクリーンショット
2023-05-23-02-07-18 のスクリーンショット

@財産

プロパティ デコレータは、メソッドをプロパティ セッターとしてラベル付けするために使用されます。 Dog の例に戻って、Dog の名前を取得するメソッドを作成しましょう。

 class Dog:
    # Creating a constructor method that takes in the dog's name
    def __init__(self, name):

         # Creating a private property name
         # The double underscores make the attribute private
         self.__name = name

    
    @property
    def name(self):
        return self.__name

これで、通常のプロパティと同じように犬の名前にアクセスできるようになりました。

 # Creating an instance of the class
foo = Dog('foo')

# Accessing the name property
print("The dog's name is:", foo.name)

コードを実行した結果は次のようになります

The dog's name is: foo 
2023-05-23-02-09-42 のスクリーンショット
2023-05-23-02-09-42 のスクリーンショット

@property.setter

property.setter デコレータは、プロパティの setter メソッドを作成するために使用されます。 @property.setter デコレータを使用するには、 property セッターを作成するプロパティの名前に置き換えます。たとえば、プロパティ foo のメソッドのセッターを作成している場合、デコレータは @foo.setter になります。以下に犬の例を示します。

 class Dog:
    # Creating a constructor method that takes in the dog's name
    def __init__(self, name):

         # Creating a private property name
         # The double underscores make the attribute private
         self.__name = name

    
    @property
    def name(self):
        return self.__name

    # Creating a setter for our name property
    @name.setter
    def name(self, new_name):
        self.__name = new_name

セッターをテストするには、次のコードを使用できます。

 # Creating a new dog
foo = Dog('foo')

# Changing the dog's name
foo.name = 'bar'

# Printing the dog's name to the screen
print("The dog's new name is:", foo.name)

コードを実行すると、次の出力が生成されます。

 The dogs's new name is: bar 
2023-05-23-11-46-25 のスクリーンショット
2023-05-23-11-46-25 のスクリーンショット

Python におけるデコレータの重要性

デコレータとは何かを説明し、デコレータの例をいくつか見てきました。次に、デコレータが Python で重要である理由について説明します。デコレータはいくつかの理由から重要です。それらのいくつかを以下にリストします。

  • コードの再利用が可能になります。上記の logging 例では、必要な関数に対して @create_logger を使用できます。これにより、関数ごとに手動でログ機能を作成することなく、すべての関数にログ機能を追加できるようになります。
  • これらを使用すると、モジュラー コードを作成できます。再びロギングの例に戻りますが、デコレータを使用すると、コア関数 (この場合は say_hello ) を、必要な他の機能 (この場合はロギング) から分離できます。
  • フレームワークとライブラリを強化します。デコレータは、追加機能を提供するために Python フレームワークとライブラリで広く使用されています。たとえば、Flask や Django などの Web フレームワークでは、ルートの定義、認証の処理、特定のビューへのミドルウェアの適用にデコレーターが使用されます。

最後の言葉

デコレータは非常に便利です。これらを使用すると、機能を変更せずに機能を拡張できます。これは、関数のパフォーマンスの時間を計測したり、関数が呼び出されるたびにログを記録したり、関数を呼び出す前に引数を検証したり、関数を実行する前に権限を検証したりする場合に便利です。デコレータを理解すると、よりきれいな方法でコードを記述できるようになります。

次に、タプルと Python での cURL の使用に関する記事を読んでください。

「 Python デコレーター: 説明 (例と使用例付き)」についてわかりやすく解説!絶対に観るべきベスト2動画

意外と簡単?意味不明なデコレータを超絶わかりやすく解説します。
【Pythonプログラミング】プロパティデコレータ @property で便利なクラスを作成しよう!〜 getter / setter 〜

Python デコレータは、Python の非常に便利な構造です。 Python でデコレータを使用すると、関数を別の関数内にラップすることで関数の動作を変更できます。デコレータを使用すると、よりクリーンなコードを記述し、機能を共有できるようになります。この記事では、デコレータの使用方法だけでなく、デコレータの作成方法についても説明します。

前提知識

Python のデコレータのトピックには、ある程度の背景知識が必要です。以下に、このチュートリアルを理解するためにすでに理解しておく必要があるいくつかの概念をリストします。必要に応じて概念をブラッシュアップできるリソースへのリンクもあります。

基本的な Python

このトピックは、より中級/上級のトピックです。そのため、学習を始める前に、データ型、関数、オブジェクト、クラスなどの Python の基本をすでに理解している必要があります。

また、ゲッター、セッター、コンストラクターなどのオブジェクト指向の概念も理解する必要があります。 Python プログラミング言語に詳しくない場合は、始めるためのリソースをいくつか紹介します。

職務は第一級市民である

基本的な Python に加えて、Python のより高度な概念についても知っておく必要があります。関数、および Python の他のほとんどすべてのものは、 int string のようなオブジェクトです。これらはオブジェクトであるため、次のようないくつかの操作を行うことができます。

  • string または int 関数の引数として渡すのと同じ方法で、関数を引数として別の関数に渡すことができます。
  • 他の string または int 値を返す場合と同様に、他の関数によって関数を返すこともできます。
  • 関数は変数に格納できる

実際、関数オブジェクトと他のオブジェクトの唯一の違いは、関数オブジェクトにはマジック メソッド __call__() が含まれていることです。

この時点で、前提条件となる知識を理解していただければ幸いです。主要なトピックについて議論を始めましょう。

Python デコレータとは何ですか?

Python デコレーターは、単に関数を引数として取り込み、渡された関数の修正バージョンを返す関数です。言い換えると、関数 foo が引数として関数 bar を取り込む場合、関数 foo はデコレーターになります。そして別の関数 baz を返します。

関数 baz baz の本体内で関数 bar への呼び出しがあるという意味で、 bar を変更したものです。ただし、 bar の呼び出しの前後では、 baz 何でもできます。それは一口でした。状況を説明するコードを次に示します。

 # Foo is a decorator, it takes in another function, bar as an argument
def foo(bar):

    # Here we create baz, a modified version of bar
    # baz will call bar but can do anything before and after the function call
    def baz():

        # Before calling bar, we print something
        print("Something")

        # Then we run bar by making a function call
        bar()

        # Then we print something else after running bar
        print("Something else")

    # Lastly, foo returns baz, a modified version of bar
    return baz

Python でデコレータを作成するには?

Python でデコレーターがどのように作成され、使用されるかを説明するために、簡単な例で説明します。この例では、関数が実行されるたびに、装飾している関数の名前をログに記録するロガー デコレーター関数を作成します。

まず、デコレータ関数を作成しました。デコレータは引数として func を受け取ります。 func は装飾している関数です。

 def create_logger(func):
    # The function body goes here

デコレーター関数内で、 func を実行する前に func の名前をログに記録する変更された関数を作成します。

 # Inside create_logger
def modified_func():
    print("Calling: ", func.__name__)
    func()

次に、 create_logger 関数は変更された関数を返します。その結果、 create_logger 関数全体は次のようになります。

 def create_logger(func):
    def modified_func():
        print("Calling: ", func.__name__)
        func()

    return modified_function

デコレータの作成が完了しました。 create_logger 関数は、デコレータ関数の簡単な例です。これは、装飾している関数である func を受け取り、別の関数 modified_func を返します。 modified_func func を実行する前に、まず func の名前をログに記録します。

Python でデコレータを使用する方法

デコレーターを使用するには、次のように @ 構文を使用します。

 @create_logger
def say_hello():
    print("Hello, World!")

これで、スクリプト内でsay_hello()を呼び出すことができ、出力は次のテキストになるはずです。

 Calling:  say_hello
"Hello, World" 
Python デコレータを使用するプログラムのスクリーンショット
Python デコレータを使用するプログラムのスクリーンショット

しかし、 @create_ create_logger は何をしているのでしょうか?そうですね、say_hello 関数にデコレータを適用しています。何をしているのかをよりよく理解するために、この段落のすぐ下のコードは、 say_hello の前に @create_logger を置くのと同じ結果を達成します。

 def say_hello():
    print("Hello, World!")

say_hello = create_logger(say_hello)

つまり、Python でデコレータを使用する 1 つの方法は、上記のコードで行ったように、関数を渡してデコレータを明示的に呼び出すことです。もう 1 つのより簡潔な方法は、 @ 構文を使用することです。

このセクションでは、Python デコレータの作成方法について説明しました。

もう少し複雑な例

上記の例は単純なケースでした。装飾している関数が引数を受け取る場合など、もう少し複雑な例があります。もう 1 つのより複雑な状況は、クラス全体を装飾したい場合です。ここではこれら両方の状況について説明します。

関数が引数を受け取るとき

デコレートしている関数が引数を受け取る場合、変更された関数は引数を受け取り、最終的に未変更の関数を呼び出すときにそれらを渡す必要があります。わかりにくいと思われる場合は、フーバー用語で説明しましょう。

foo はデコレーター関数、 bar は装飾する関数、 baz は装飾された bar であることを思い出してください。その場合、 bar は引数を受け取り、 baz の呼び出し中にそれらを baz に渡します。概念を明確にするためのコード例を次に示します。

 def foo(bar):
    def baz(*args, **kwargs):
        # You can do something here
        ___
        # Then we make the call to bar, passing in args and kwargs
        bar(*args, **kwargs)
        # You can also do something here
        ___

    return baz

*args **kwargs に見慣れない場合は、これらはそれぞれ、位置引数とキーワード引数への単なるポインタです。

baz 引数にアクセスできるため、 bar を呼び出す前に引数の検証を実行できることに注意することが重要です。

例としては、デコレータ関数 ensure_string あり、デコレータ関数に渡される引数が文字列であることを保証する場合が考えられます。次のように実装します。

 def ensure_string(func):
    def decorated_func(text):
        if type(text) is not str:
             raise TypeError('argument to ' + func.__name__ + ' must be a string.')
        else:
             func(text)

    return decorated_func

次のように say_hello 関数を装飾できます。

 @ensure_string
def say_hello(name):
    print('Hello', name)

次に、これを使用してコードをテストできます。

 say_hello('John') # Should run just fine
say_hello(3) # Should throw an exception

そして、次の出力が生成されるはずです。

 Hello John
Traceback (most recent call last):
   File "/home/anesu/Documents/python-tutorial/./decorators.py", line 20, in <module> say hello(3) # should throw an exception
   File "/home/anesu/Documents/python-tu$ ./decorators.pytorial/./decorators.py", line 7, in decorated_func raise TypeError('argument to + func._name_ + must be a string.')
TypeError: argument to say hello must be a string. $0 
2023-05-23-02-33-18 のスクリーンショット
2023-05-23-02-33-18 のスクリーンショット

「John」は文字列であるため、予想どおり、スクリプトは「Hello John」を出力できました。 「Hello 3」を出力しようとすると、「3」が文字列ではないため、例外がスローされました。 ensure_string デコレータは、文字列を必要とする関数の引数を検証するために使用できます。

クラスの飾りつけ

関数を装飾するだけでなく、クラスを装飾することもできます。デコレータをクラスに追加すると、デコレータ メソッドがクラスのコンストラクタ/イニシエーター メソッド (__init__) を置き換えます。

foo-bar に戻ります。foo がデコレータ、Bar が装飾対象のクラスであるとします。その場合、foo は Bar.__init__ を装飾します。これは、 Bar 型のオブジェクトがインスタンス化される前に何かをしたい場合に便利です。

つまり、次のコードは

def foo(func):
    def new_func(*args, **kwargs):
        print('Doing some stuff before instantiation')
        func(*args, **kwargs)

    return new_func

@foo
class Bar:
    def __init__(self):
        print("In initiator")

と同等です

def foo(func):
    def new_func(*args, **kwargs):
        print('Doing some stuff before instantiation')
        func(*args, **kwargs)

    return new_func

class Bar:
    def __init__(self):
        print("In initiator")


Bar.__init__ = foo(Bar.__init__)

実際、2 つのメソッドのいずれかを使用して定義された Bar クラスのオブジェクトをインスタンス化すると、同じ出力が得られます。

 Doing some stuff before instantiation
In initiator 
2023-05-23-02-20-38 のスクリーンショット
2023-05-23-02-20-38 のスクリーンショット

Python のデコレータの例

独自のデコレータを定義できますが、Python にすでに組み込まれているものもあります。 Python で使用される一般的なデコレータの一部を次に示します。

@静的メソッド

静的メソッドは、クラスが装飾しているメソッドが静的メソッドであることを示すためにクラスで使用されます。静的メソッドは、クラスをインスタンス化せずに実行できるメソッドです。次のコード例では、静的メソッド bark を使用してクラス Dog を作成します。

 class Dog:
    @staticmethod
    def bark():
        print('Woof, woof!')

これで、次のように bark メソッドにアクセスできるようになります。

 Dog.bark()

コードを実行すると、次の出力が生成されます。

 Woof, woof! 
2023-05-23-02-02-07 のスクリーンショット
2023-05-23-02-02-07 のスクリーンショット

デコレータの使用方法のセクションで述べたように、デコレータは 2 つの方法で使用できます。 @ 構文は、2 つのうちの 1 つとしてより簡潔です。もう 1 つの方法は、デコレーター関数を呼び出し、装飾したい関数を引数として渡します。つまり、上のコードは以下のコードと同じことを実現します。

 class Dog:
    def bark():
        print('Woof, woof!')

Dog.bark = staticmethod(Dog.bark)

そして、同じ方法で bark メソッドを使用することもできます。

 Dog.bark()

そして、同じ出力が生成されます

Woof, woof! 
2023-05-23-02-02-07-1 のスクリーンショット
2023-05-23-02-02-07-1 のスクリーンショット

ご覧のとおり、最初の方法の方がすっきりしており、コードを読み始める前から関数が静的関数であることがより明らかです。そのため、残りの例では最初の方法を使用します。ただし、2 番目の方法は代替手段であることを覚えておいてください。

@クラスメソッド

このデコレータは、デコレータが装飾しているメソッドがクラス メソッドであることを示すために使用されます。クラス メソッドは、呼び出す前にクラスをインスタンス化する必要がないという点で静的メソッドと似ています。

ただし、主な違いは、クラス メソッドはクラス属性にアクセスできるのに対し、静的メソッドはアクセスできないことです。これは、Python が呼び出されるたびに、そのクラスをクラス メソッドの最初の引数として自動的に渡すためです。 Python でクラス メソッドを作成するには、 classmethod デコレータを使用できます。

 class Dog:
    @classmethod
    def what_are_you(cls):
        print("I am a " + cls.__name__ + "!")

コードを実行するには、クラスをインスタンス化せずにメソッドを呼び出すだけです。

 Dog.what_are_you()

そして出力は次のようになります。

 I am a Dog! 
2023-05-23-02-07-18 のスクリーンショット
2023-05-23-02-07-18 のスクリーンショット

@財産

プロパティ デコレータは、メソッドをプロパティ セッターとしてラベル付けするために使用されます。 Dog の例に戻って、Dog の名前を取得するメソッドを作成しましょう。

 class Dog:
    # Creating a constructor method that takes in the dog's name
    def __init__(self, name):

         # Creating a private property name
         # The double underscores make the attribute private
         self.__name = name

    
    @property
    def name(self):
        return self.__name

これで、通常のプロパティと同じように犬の名前にアクセスできるようになりました。

 # Creating an instance of the class
foo = Dog('foo')

# Accessing the name property
print("The dog's name is:", foo.name)

コードを実行した結果は次のようになります

The dog's name is: foo 
2023-05-23-02-09-42 のスクリーンショット
2023-05-23-02-09-42 のスクリーンショット

@property.setter

property.setter デコレータは、プロパティの setter メソッドを作成するために使用されます。 @property.setter デコレータを使用するには、 property セッターを作成するプロパティの名前に置き換えます。たとえば、プロパティ foo のメソッドのセッターを作成している場合、デコレータは @foo.setter になります。以下に犬の例を示します。

 class Dog:
    # Creating a constructor method that takes in the dog's name
    def __init__(self, name):

         # Creating a private property name
         # The double underscores make the attribute private
         self.__name = name

    
    @property
    def name(self):
        return self.__name

    # Creating a setter for our name property
    @name.setter
    def name(self, new_name):
        self.__name = new_name

セッターをテストするには、次のコードを使用できます。

 # Creating a new dog
foo = Dog('foo')

# Changing the dog's name
foo.name = 'bar'

# Printing the dog's name to the screen
print("The dog's new name is:", foo.name)

コードを実行すると、次の出力が生成されます。

 The dogs's new name is: bar 
2023-05-23-11-46-25 のスクリーンショット
2023-05-23-11-46-25 のスクリーンショット

Python におけるデコレータの重要性

デコレータとは何かを説明し、デコレータの例をいくつか見てきました。次に、デコレータが Python で重要である理由について説明します。デコレータはいくつかの理由から重要です。それらのいくつかを以下にリストします。

  • コードの再利用が可能になります。上記の logging 例では、必要な関数に対して @create_logger を使用できます。これにより、関数ごとに手動でログ機能を作成することなく、すべての関数にログ機能を追加できるようになります。
  • これらを使用すると、モジュラー コードを作成できます。再びロギングの例に戻りますが、デコレータを使用すると、コア関数 (この場合は say_hello ) を、必要な他の機能 (この場合はロギング) から分離できます。
  • フレームワークとライブラリを強化します。デコレータは、追加機能を提供するために Python フレームワークとライブラリで広く使用されています。たとえば、Flask や Django などの Web フレームワークでは、ルートの定義、認証の処理、特定のビューへのミドルウェアの適用にデコレーターが使用されます。

最後の言葉

デコレータは非常に便利です。これらを使用すると、機能を変更せずに機能を拡張できます。これは、関数のパフォーマンスの時間を計測したり、関数が呼び出されるたびにログを記録したり、関数を呼び出す前に引数を検証したり、関数を実行する前に権限を検証したりする場合に便利です。デコレータを理解すると、よりきれいな方法でコードを記述できるようになります。

次に、タプルと Python での cURL の使用に関する記事を読んでください。

「 Python デコレーター: 説明 (例と使用例付き)」についてわかりやすく解説!絶対に観るべきベスト2動画

意外と簡単?意味不明なデコレータを超絶わかりやすく解説します。
【Pythonプログラミング】プロパティデコレータ @property で便利なクラスを作成しよう!〜 getter / setter 〜