デコレータは追加機能で関数を拡張できますが、多くの場合、汎用デコレータが元の関数を置き換えます。 「args、*kwargs」のようなワイルドカード署名を使用した署名。これは、特にドキュメントを生成したり、関数のメタデータをイントロスペクトしたりする場合に問題になる可能性があります。
デコレータ モジュールは簡単な解決策を提供します。デコレータ関数をdecorator.decoratorでラップすることで、元の関数の署名を維持できます:
<code class="python">import decorator @decorator.decorator def args_as_ints(f, *args, **kwargs): args = [int(x) for x in args] kwargs = dict((k, int(v)) for k, v in kwargs.items()) return f(*args, **kwargs) @args_as_ints def funny_function(x, y, z=3): """Computes x*y + 2*z""" return x*y + 2*z</code>
このアプローチでは、元の関数の署名が維持されます:
<code class="python">help(funny_function) # Help on function funny_function in module __main__: # # funny_function(x, y, z=3) # Computes x*y + 2*z</code>
Python 3.4 以降では、functools.wraps() は元の関数シグネチャを自動的に保存します。
<code class="python">import functools def args_as_ints(func): @functools.wraps(func) def wrapper(*args, **kwargs): args = [int(x) for x in args] kwargs = dict((k, int(v)) for k, v in kwargs.items()) return func(*args, **kwargs) return wrapper @args_as_ints def funny_function(x, y, z=3): """Computes x*y + 2*z""" return x*y + 2*z help(funny_function) # Help on function funny_function in module __main__: # # funny_function(x, y, z=3) # Computes x*y + 2*z</code>
ただし、functools.wraps() は、Python の以前のバージョンではこの動作を示しませんでした。 .
関数の docstring で署名を複製したり、特定の署名ごとにカスタム デコレータを作成したりすることは、重複とメンテナンスの問題を引き起こす欠陥のある回避策です。
デコレータ モジュールを利用するか、Python 3.4 の functools.wraps() を利用することで、元の関数のシグネチャを維持しながらデコレータを汎用的に使用でき、堅牢なドキュメントとイントロスペクション機能が確保されます。
以上が汎用デコレータを使用するときに元の関数のシグネチャを保持するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。