ホームページ >バックエンド開発 >Python チュートリアル >Python のデコレーターとは何か、またその使用方法

Python のデコレーターとは何か、またその使用方法

WBOY
WBOY転載
2023-05-15 14:01:061571ブラウズ
使用環境は次のとおりです。 Python 3.6.8

Python のデコレーターとは何か、またその使用方法

デコレータとは

理解する前にデコレータを使用するには、クロージャ関数とは何かを理解する必要があります。

クロージャー関数

デモを作成して、クロージャー関数とは何かを説明してみましょう。

def exterFunc(x):
  def innerFunc(y):
    return x * y
  
  return innerFunc

def main() -> None:
  f = exterFunc(6)
  result = f(5)

  print(result)

if __name__ == '__main__':
  main()

ご覧のとおり、上記のコードに示されているように、いわゆるクロージャ関数は次のことを指します: クロージャ関数は、関数内で定義された関数を指します。内部関数は外部変数にアクセスできます。 . 外部関数では内部関数を戻り値として返します。

上記の例でわかるように、関数 exterFunc を定義しました。この関数は、exterFunc## で仮パラメータ x を受け取ります。 #innerFunc は関数で定義されており、仮パラメータ y も受け取ります。innerFunc 関数では、x * y が返されますはい、内部関数は外部関数によって渡された変数にアクセスでき、最終的に戻り値として exterFunc を返します。これがクロージャ関数です。

最も単純なデコレータ

デコレータは、関数を仮パラメータとして受け取り、新しい関数を返すことができる非常に特殊な関数です。前回の記事でジェネレータを紹介しました。関数のメモリ操作ステータスを出力するために

memory_profiler ライブラリを使用したことをまだ覚えていますか?使用したデコレータです。

Python のデコレーターとは何か、またその使用方法

python デコレータを説明する最も簡単な例を書くことができます。つまり、

def foo(func):
    def wrapper():
        print("装饰器开始运行了")
        func()
        print("装饰器结束运行了")

    return wrapper

@foo
def sayHello():
    print("hello pdudo in juejin")

def main() -> None:
  sayHello()

if __name__ == '__main__':
  main()

上記のコードでは、デコレータ

foo が定義されており、foo は関数を渡す必要があります。foo には関数 wrapper が含まれています。このような関数でラップされた関数をクロージャ関数と呼びます。クロージャ関数については後で紹介します。さらに、wrapper 関数では、func 関数の実行時に前後のステートメントを実行できます。

デコレータを呼び出す必要がある場合は、

@関数名を追加するだけです。

デコレータが必要な理由

この問題を説明するには、デコレータがどのような問題を解決するかを見てみましょう:

  • ソリューション コードの反復性。多くの場合、同様の関数を実装する必要がある場合、その関数を抽出してデコレータとして呼び出して、コードの重複を避けることができます。

  • コードの可読性の向上。デコレータを使用すると、例外の処理やログの記録など、元のコードを変更せずに関数の前後にコードを追加できます。デコレータを使用できます。追加関数を分離するコードの可読性を高めるための関数の主要な機能から。

ここまで述べたので、最も単純な例を列挙し、デコレータを使用して関数の実行時間を出力してみましょう。

import time

def getExecTimers(func):
  def wrapper():
    startTimes = time.time()
    func()
    endTimes = time.time()
    print("函数运行时间: " , endTimes - startTimes ,"s")
  return wrapper

@getExecTimers
def testFunc():
  print("开始执行函数")
  time.sleep(5)
  print("函数执行结束")

def main() -> None:
  testFunc()
  
if __name__ == '__main__':
  main()

このデコレータは関数の実行時間を記録します。ご覧のとおり、この関数に追加関数を追加しましたが、元の関数は変更していません。

上記のケースは、デコレータを使用する必要がある理由を証明できるはずです。

デコレータの使用法

上記では、デコレータを作成する最も簡単な方法について説明し、関数の実行時間を出力する小さな関数を作成しました。次に、デコレータを記述する他の方法を検討する必要があります。

それは構文シュガーを使用して呼び出されませんか?

上記のデコレータを呼び出したときに、

@ デコレータ名を使用したことを覚えていますか?実際、これは python の構文シュガーです。構文シュガーを使用しない場合は、次のように使用する必要があります:

def foo(func):
    def wrapper():
        print("装饰器开始运行了")
        func()
        print("装饰器结束运行了")

    return wrapper


def sayHello():
    print("hello pdudo in juejin")

def main() -> None:
  f1 = sayHello
  f2 = foo(f1)

  f2()

if __name__ == '__main__':
  main()

完全な記述方法は次のようになります。コードです。これは完全なクロージャです。パッケージ呼び出しロジックです。

f1 = sayHello
f2 = foo(f1)

f2()

関数の前に

@ デコレータ名を追加することは、python

パラメータ付きデコレータの一種の構文糖衣です

python には、*args**kwargs という 2 つの特別な変数があり、どちらも不定のパラメータを処理するために使用され、それぞれの意味は

  • *args: パラメータはタプルにパックされます

  • **kwargs: パックされた辞書は関数に渡されます

  • def foo(func):
        def wrapper(*args,**kwargs):
            print("装饰器开始运行了")
            print("装饰器捕获到的参数: " ,args,**kwargs)
            func(*args,**kwargs)
            print("装饰器结束运行了")
    
        return wrapper
    
    @foo
    def sayHello(a,b,c,dicts):
        print("传入的参数: " , a,b,c)
        print("传入的参数: " , dicts)
    
    def main() -> None:
      sayHello(1,2,3,{"name":"juejin"})
    
    if __name__ == '__main__':
      main()
デコレータで、パラメータを関数に渡したい場合は、それが必要です。パラメータは最初にデコレータに渡されます。

def foo(func):
    def wrapper(*args,**kwargs):
        print("装饰器开始运行了")
        print("装饰器捕获到的参数: " ,args,**kwargs)
        func(*args,**kwargs)
        print("装饰器结束运行了")

まず、転送呼び出しを行うときに、

wrapper仮パラメータを呼び出して、デコレータで受信した後に渡す必要があります。それを受け取り、受け取った後関数 func に渡します。

以上がPython のデコレーターとは何か、またその使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。