私はPythonを学んで
いて、デコレータが関数に機能を追加するということを理解している方法で立ち往生し
ています。数値が偶数かどうかをチェックする単純な関数を作成し、
次に絶対値を取ることを追加するデコレータを作成しました。
def decorate(func):
def is_even_new(*args,**kwargs):
num = abs(*args,**kwargs)
func(num)
return is_even_new()
@decorate
def is_even(x):
if x%2 == 0:
return True
else:
return False
is_even(8)
しかし、TypeErrorが発生し続けます。abs()は引数を1つだけ取ります(0が指定さ
れています)。コードに問題があるのでしょうか、それともデコレータの理解が間違っているのでしょうか。
関数を装飾するときは、装飾された関数自体を返す必要があります。
def decorate(func):
def is_even_new(*args,**kwargs):
num = abs(*args,**kwargs)
func(num)
return is_even_new
装飾された関数を呼び出してそれを返すのではなく:
def decorate(func):
def is_even_new(*args,**kwargs):
num = abs(*args,**kwargs)
func(num)
return is_even_new()
(余分な括弧に注意してください)。この最後の例では、関数を@decorate
でデコレートすると、デコレータはこの内部関数is_even_new
を定義し、後者を返す代わりに、引数なしでそれを呼び出そうとしますis_even_new()
。これは、TypeError
:abs
expects(正確に)1つの引数を取得している理由でもありますが、何も指定していません。
Pythonの関数は他の関数(「第一級市民」)と同じようにオブジェクトであるため、名前で直接参照できることを忘れないでください。
また、推奨事項として、で装飾された関数が@decorate
(のようにis_even
)1つの引数しか受け取らないことがわかっている場合は、変数引数とキーワード引数を使用せず、1つのパラメーターも受け取るようにdecorate関数を定義してください。
import functools
def decorate(func):
@functools.wraps(func)
def decorated(x):
func(abs(x))
return decorated
これにより、エラーメッセージがより役立つようになります(abs
電話で発生する代わりに、
または、abs
たとえば最初の引数にのみ適用する場合は、次のようにします。
def decorate(func):
@functools.wraps(func)
def decorated(x, *args, **kwargs):
func(abs(x), *args, **kwargs)
return decorated
また、に気付くでしょう@functools.wraps
。これは、デコレータから返すようなラッパー関数を定義するための非常に便利な標準ライブラリユーティリティです。それはのような特殊な属性設定し__name__
、__module__
それは基本的に包まれた機能のように見えるようにラッパー関数に、など。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加