次の記事では、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 サイトの他の関連記事を参照してください。