Pythonはどうやって飾りを解除しますか?
問題
一つの飾り器はもう一つの関数に作用しています。元の未包装のその関数に直接アクセスしたいです。
ソリューション
飾り器が@wrapsで実現されると仮定すれば、__u uにアクセスすることができます。wrapped_u属性を使って原始関数にアクセスします。
未包装の原始関数に直接アクセスすることは、デバッグ、内省、その他の関数の操作において有用である。しかし、ここでのスキームは包装器に
複数の包装器がある場合、
以上はPythonがどうやって装飾器の詳細を解除しますか?
一つの飾り器はもう一つの関数に作用しています。元の未包装のその関数に直接アクセスしたいです。
ソリューション
飾り器が@wrapsで実現されると仮定すれば、__u uにアクセスすることができます。wrapped_u属性を使って原始関数にアクセスします。
>>> @somedecorator
>>> def add(x, y):
... return x + y
...
>>> orig_add = add.__wrapped__
>>> orig_add(3, 4)
7
>>>
討論する未包装の原始関数に直接アクセスすることは、デバッグ、内省、その他の関数の操作において有用である。しかし、ここでのスキームは包装器に
@wraps
を正しく使用した場合、または __wrapped__
の属性を直接設定した場合にのみ適用されます。複数の包装器がある場合、
__wrapped__
属性にアクセスする行為は予知できないので、避けるべきです。Pythoon 3.3では、すべての包装層を省略します。たとえば、下記のコードがあります。
from functools import wraps
def decorator1(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('Decorator 1')
return func(*args, **kwargs)
return wrapper
def decorator2(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('Decorator 2')
return func(*args, **kwargs)
return wrapper
@decorator1
@decorator2
def add(x, y):
return x + y
次はPythoon 3.3でテストします。
>>> add(2, 3)
Decorator 1
Decorator 2
5
>>> add.__wrapped__(2, 3)
5
>>>
次はPythoon 3.4でテストします。
>>> add(2, 3)
Decorator 1
Decorator 2
5
>>> add.__wrapped__(2, 3)
Decorator 2
5
>>>
最後に言いたいのは、すべての飾り器が@wraps
を使っているわけではないので、ここの案は全部適用されていません。特に、内蔵された装飾器@staticmethod
および @classmethod
は、この約束に従わない(オリジナル関数を属性__func__
に格納する)。以上はPythonがどうやって装飾器の詳細を解除しますか?