Объект не может быть вызван после добавления метода __call__ к экземпляру

У меня есть следующий код

import numpy as np

class Estimator(object):
    name = None

    def __init__(self):
        self.__call__ = self._call

class Mean(Estimator):
    name = 'mean'

    def _call(self, data):
        return np.mean(data)

data = np.arange(10)

теперь, почему я не могу использовать второй класс как функтор как первый?

Кажется, это работает:

M = Mean()
print M.__call__(data)  # -> 4.5

M имеет метод __call__:

print '__call__' in dir(M)  # -> True

но это не работает

print M(data)

Я получил:

TypeError: 'Mean' object is not callable

person Ruggero Turra    schedule 13.03.2014    source источник
comment
Специальные методы ищутся в классе, а не в экземплярах.   -  person Ashwini Chaudhary    schedule 14.03.2014


Ответы (1)


Как говорит Ашвини, «специальные методы ищутся в классе, а не в экземплярах».

Таким образом, следующее будет работать так, как вы ожидаете (хотя я не могу представить, почему вы этого хотите):

class Estimator(object):
    name = None

    def __init__(self):
        self.__class__.__call__ = self.__class__._call

class Mean(Estimator):
    name = 'mean'

    def _call(self, data):
        return np.mean(data)
person isedev    schedule 13.03.2014
comment
Установка метода __call__ для всего класса на _call нового экземпляра означает, что несколько оценок одного и того же класса не будут работать правильно. - person user2357112 supports Monica; 14.03.2014
comment
@ user2357112 объясните, что ... в данном примере он устанавливает Mean.__call__ на Mean._call. Какое отношение он имеет к экземпляру? - person isedev; 14.03.2014
comment
Нет, он устанавливает Mean.__call__ в self._call, связанный метод. - person user2357112 supports Monica; 14.03.2014
comment
@user2357112 user2357112 хорошо, я понимаю вашу точку зрения ... обновлено, чтобы действовать в соответствии с классом. - person isedev; 14.03.2014
comment
@isedev: мне это нужно, потому что я хочу решить, какую функцию вызывать с помощью __call__ при построении класса. В моем реальном коде у меня есть две функции _call, и базовый класс решает, какую из них использовать, в зависимости от аргумента __init__. - person Ruggero Turra; 14.03.2014