ホームページ  >  記事  >  バックエンド開発  >  Pythonデコレータの定義と応用例を解説

Pythonデコレータの定義と応用例を解説

乌拉乌拉~
乌拉乌拉~オリジナル
2018-08-22 16:17:371085ブラウズ

次の記事では、Python デコレータとは何かについて学びましょう。 Python デコレータの関連知識と Python デコレータの使用法について学びます。さて、早速、次の記事から始めましょう。

pythondecorator

要するに、pythonDecorator は、元の関数の機能を拡張するために使用される関数です。この関数は特別です。戻り値も関数であるということです。Python デコレーターを使用する利点は、元の関数のコードを変更せずに関数に新しい関数を追加できることです。

関数はオブジェクトでもあり、関数オブジェクトは変数に代入できるため、変数を介して関数を呼び出すこともできます。

>>> def now():
...     print('2015-3-25')
...
>>> f = now
>>> f()
2015-3-25

関数オブジェクトには __name__ 属性があり、関数の名前を取得できます。

>>> now.__name__
'now'
>>> f.__name__
'now'

次に、now() 関数の関数を拡張したいとします。たとえば、次のようになります。関数呼び出しの前後に自動的にログを出力するが、now() 関数の定義を変更したくない コードの実行中に動的に関数を追加するこの方法は、「デコレーター」と呼ばれます。

本質的に、デコレータは関数を返す高階関数です。したがって、ログを出力できるデコレータを定義する必要があります。これは次のように定義できます。

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)   
   return wrapper

上記のログを観察してください。これはデコレータであるため、関数をパラメータとして受け取り、関数を返します。 Python の @ 構文を使用して、関数の定義にデコレーターを配置する必要があります。

@log
def now():
    print('2015-3-25')

now() 関数を呼び出すと、now() 関数自体が実行されるだけでなく、実行前に行が出力されます。 now() 関数のログ:

>>> now()
call now():
2015-3-25

now() 関数の定義に @log を置くことは、次のステートメントを実行することと同じです:

now = log(now)

log() はデコレータであり、関数を返すため、したがって、元々は now() 関数がまだ存在しますが、現在は同じ名前の now 変数が新しい関数を指しているため、now() を呼び出すと新しい関数、つまり log() で返されるwrapper() 関数が実行されます。 ) 関数。

wrapper() 関数のパラメータ定義は (*args, **kw) であるため、wrapper() 関数は任意のパラメータを使用した呼び出しを受け入れることができます。 Wrapper() 関数内では、最初にログが出力され、次に元の関数が呼び出されます。

デコレータ自体がパラメータを渡す必要がある場合は、デコレータを返す高階関数を作成する必要がありますが、その作成はより複雑になります。たとえば、ログのテキストをカスタマイズするには:

def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))          
          return func(*args, **kw)  
        return wrapper  
     return decorator

この 3 層のネストされたデコレータの使用法は次のとおりです:

@log('execute')
 def now():
   print('2015-3-25')

実行結果は次のとおりです:

>>> now()
execute now():
2015-3-25

と 2 層のネストされたデコレータ デコレータと比較すると、3 レベルのネストの効果は次のとおりです:

>>> now = log('execute')(now)

上記のステートメントを分析してみましょう。まず、デコレータを返す log('execute') を実行します。関数を呼び出し、返された関数とパラメーターを呼び出します。これが now 関数であり、戻り値は最終的にはラッパー関数になります。

デコレータの上記 2 つの定義には問題ありませんが、最後のステップがまだ 1 つ残っています。関数もオブジェクトであると述べたので、関数には __name__ などの属性がありますが、decorator によって装飾された関数を見ると、その __name__ は元の 'now' から 'wrapper' に変更されています。返されたwrapper()関数の名前は「wrapper」です。元の関数の__name__とその他の属性をwrapper()関数にコピーする必要があります。そうしないと、関数シグネチャに依存する一部のコードが正しく実行されません。

wrapper.__name__ = func.__name__ のようなコードを記述する必要はありません。Python の組み込み functools.wraps がこれを行います。したがって、完全なデコレータは次のように記述されます:

>>> now.__name__'
wrapper'

または、パラメータ付きのデコレータの場合:

import functools
   def log(func):
   @functools.wraps(func)
     def wrapper(*args, **kw)
       print('call %s():' % func.__name__)      
     return func(*args, **kw)    
   return wrapper

import functools は functools モジュールをインポートします。モジュールの概念については後述します。ここで、wrapper() を定義する前に @functools.wraps(func) を追加することを忘れないでください。

以上がこの記事で説明する内容の全てですが、この記事では主に

pythondecorator

に関する知識を紹介しますので、上記の内容を理解するために活用していただければ幸いです。この記事で説明したことがあなたのお役に立ち、Python の学習が容易になることを願っています。 関連知識の詳細については、php 中国語 Web サイトの

Python チュートリアル

列を参照してください。

以上がPythonデコレータの定義と応用例を解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。