Pythonでは、同じデコレータを使用することの違いは何ですか括弧ありとなし?
例えば:
括弧なし:
@some_decorator
def some_method():
pass
括弧付き:
@some_decorator()
def some_method():
pass
some_decorator
最初のコードスニペットは通常のデコレータです:
@some_decorator
def some_method():
pass
に相当
some_method = some_decorator(some_method)
一方、 some_decorator
2番目のコードスニペットでは、デコレータを返す呼び出し可能オブジェクトです。
@some_decorator()
def some_method():
pass
に相当
some_method = some_decorator()(some_method)
Duncanのコメントで指摘されているように、一部のデコレータは双方向で機能するように設計されています。このようなデコレータのかなり基本的な実装は次のとおりです。
def some_decorator(arg=None):
def decorator(func):
def wrapper(*a, **ka):
return func(*a, **ka)
return wrapper
if callable(arg):
return decorator(arg) # return 'wrapper'
else:
return decorator # ... or 'decorator'
pytest.fixture
はより複雑な例です。
簡単に言うと、デコレータを使用すると、関数やクラスのグループにまったく変更を加えることなく、それらに機能を追加できます。
_@some_decorator
_と@some_decorator()
の違いを理解するための鍵は、前者はデコレータであり、後者はデコレータを返す関数(または呼び出し可能)であることです。
各ケースの実装を見ると、違いを理解するのに役立つと思います。
@some_decorator
__def some_decorator(func):
def wrapper(func):
return func(*args, **kwargs)
return wrapper
_
アプリケーション:
_@some_decorator
def some_method():
pass
_
同等:
_some_method = some_decorator(some_method)
_
@some_decorator()
_def some_decorator():
def decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
return decorator
_
アプリケーション:
_@some_decorator()
def some_method():
pass
_
同等:
_some_method = some_decorator()(some_method)
_
_some_decorator
_が単なるデコレータであるのに対して、@some_decorator()
はデコレータを返す関数であることが簡単にわかるようになりました。一部のデコレータは双方向で機能するように作成されていることに注意してください。
したがって、以前のバージョンの方が単純に見えるのに、なぜこの2つのケースがあるのか疑問に思われるかもしれません。答えは、デコレータに引数を渡したい場合、@some_decorator()
を使用するとこれが可能になるということです。実際のコードをいくつか見てみましょう。
_def some_decorator(arg1, arg2):
def decorator(func):
def wrapper(*args, **kwargs):
print(arg1)
print(arg2)
return func(*args, **kwargs)
return wrapper
return decorator
_
アプリケーション:
_@some_decorator('hello', 'bye')
def some_method():
pass
_
同等:
_some_method = some_decorator('hello', 'bye')(some_method)
_
注:デコレータは関数またはクラスとして実装できることを言及する価値があると思います。詳細は this を確認してください。
デコレーター内で引数を使用する実際に機能するコード:
def someDecorator(arg=None):
def decorator(func):
def wrapper(*a, **ka):
if not callable(arg):
print (arg)
return func(*a, **ka)
else:
return 'xxxxx'
return wrapper
if callable(arg):
return decorator(arg) # return 'wrapper'
else:
return decorator # ... or 'decorator'
@someDecorator(arg=1)
def my_func():
print('aaa')
@someDecorator
def my_func1():
print('bbb')
if __name__ == "__main__":
my_func()
my_func1()
出力は次のとおりです。
1
aaa