Обертывание специальным методом работает, но не оказывает желаемого влияния на поведение экземпляра.
Например, украшение метода a.__call__
(экземпляра a) действительно вступит в силу, если я вызову a.__call__(x)
, но не если я вызову a(x)
.
. Рассмотрим следующеефункция, которая делает декоратор, который предварительно обрабатывает ввод:
def input_wrap_decorator(preprocess):
def decorator(func):
def func_wrapper(*args, **kwargs):
return func(preprocess(*args, **kwargs))
return func_wrapper
return decorator
Рассмотрим этот простой класс:
class A:
def __call__(self, k):
return "{}({})".format(self.__class__.__name__, k)
Демонстрация его удивительной функциональности:
>>> a = A()
>>> a(7)
'A(7)'
Теперь произнеситеЯ хочу сделать что-то критическое: умножить все входные данные на __call__
на 10, используя input_wrap_decorator
.Вот что происходит:
>>> a = A()
>>> a.__call__ = input_wrap_decorator(preprocess=lambda x: x * 10)(a.__call__)
>>> a.__call__(7) # __call__ works as expected
'A(70)'
>>> a(7) # but a(.) does not!
'A(7)'
Происходит что-то неясное, что знает только взрослый питон ...