装飾された関数の署名の保持
デコレーターは、Python 関数の機能を拡張するための強力なツールです。ただし、元の関数の署名がわかりにくくなる場合があります。これは、ドキュメント、デバッグ、および自動化ツールにとって問題となる可能性があります。
問題:
すべての引数を整数に変換する汎用デコレータを考えてみましょう:
<code class="python">def args_as_ints(f): def g(*args, **kwargs): args = [int(x) for x in args] kwargs = dict((k, int(v)) for k, v in kwargs.items()) return f(*args, **kwargs) return g</code>
装飾は期待どおりに機能しますが、装飾された関数のシグネチャは「args, *kwargs」に置き換えられ、元の引数に関する情報が失われます。
回避策:
いくつかの回避策が存在しますが、完全に満足できるものはありません:
解決策:
デコレータ モジュールは洗練された解決策を提供します:
<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)</code>
このデコレータは、ラップされた関数に引数として渡すことで、元の関数のシグネチャを保持します。
改良されたデコレータ:
<code class="python">@args_as_ints def funny_function(x, y, z=3): """Computes x*y + 2*z""" return x*y + 2*z</code>
装飾された関数 funny_function は、保持されます。元の署名:
>>> help(funny_function) Help on function funny_function in module __main__: funny_function(x, y, z=3) Computes x*y + 2*z
Python 3.4 :
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</code>
これらの手法を使用することで、デコレータは元の署名を維持しながら関数の機能を強化し、コードベースの明確さと一貫性を確保できます。
以上がPython でデコレータを使用するときに関数のシグネチャを保持するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。