Когда использование __call__ хорошая идея? - PullRequest
15 голосов
/ 30 июля 2010

Каково мнение людей об использовании __call__.Я очень редко видел, как он используется, но я думаю, что это очень удобный инструмент для использования, когда вы знаете, что класс будет использоваться для некоторого поведения по умолчанию.

Ответы [ 4 ]

16 голосов
/ 30 июля 2010

Я думаю, что ваша интуиция права.

Исторически вызываемые объекты (или то, что я иногда слышал как «функторы») использовались в мире ОО для имитации замыканий. В C ++ они часто незаменимы.

Однако у __call__ есть немало конкурентов в мире Python:

  • Обычный именованный метод, поведение которого иногда намного проще вывести из имени. Можно преобразовать в связанный метод, который можно вызывать как функцию.
  • Замыкание, полученное путем возврата функции, определенной во вложенном блоке.
  • Лямбда, которая является ограниченным, но быстрым способом сделать закрытие.
  • Генераторы и сопрограммы, чьи тела удерживают накопленное состояние так же, как и функтор.

Я бы сказал, что время использования __call__ - это когда вам не подходит один из вариантов выше. Проверьте следующие критерии, возможно:

  • Ваш объект имеет состояние.
  • Для вашего класса существует явное "первичное" поведение, которое глупо называть. Например. если вы пишете run() или doStuff() или go() или когда-либо популярное и постоянно избыточное doRun(), у вас может быть кандидат.
  • Ваш объект имеет состояние, которое превышает ожидаемое от функции генератора.
  • Ваш объект оборачивает, эмулирует или абстрагирует концепцию функции.
  • У вашего объекта есть другие вспомогательные методы, которые концептуально связаны с вашим основным поведением.

Один пример, который мне нравится, это объекты команд UI. Разработанный таким образом, чтобы их основной задачей было выполнение команд, но с дополнительными методами, например, для управления их отображением в качестве пункта меню, мне кажется, что это то, для чего вам все еще нужен вызываемый объект. *

4 голосов
/ 30 июля 2010

Используйте его, если вам нужно, чтобы ваши объекты можно было вызывать, вот для чего он нужен

Я не уверен, что вы подразумеваете под поведением по умолчанию

В одном месте я нашел это особенно полезнымэто когда используется обертка или что-то подобное, когда объект вызывается глубоко внутри какой-то структуры / библиотеки.

1 голос
/ 30 июля 2010

В более общем смысле, Python имеет lot методов двойного подчеркивания. Они там по причине: они - способ перегрузки операторов Python. Например, если вам нужен новый класс, в котором помимо этого, я не знаю, печатается "foo", вы определяете методы __add__ и __radd__. В этом нет ничего хорошего или плохого, как и ничего хорошего или плохого в использовании for циклов.

На самом деле, использование __call__ часто является более Pythonic подходом, потому что он способствует ясности кода. Вы можете заменить MyCalculator.calculateValues( foo ) на MyCalculator( foo ), скажем.

0 голосов
/ 30 июля 2010

Обычно используется, когда класс используется как функция с некоторым контекстом экземпляра, например, с некоторым классом DecoratorClass, который будет использоваться как @DecoratorClass('some param'), поэтому «некоторый параметр» будет храниться в пространстве имен экземпляра, а затем вызываться как фактический декоратор.

Это не очень полезно, когда ваш класс предоставляет некоторые другие методы, поскольку обычно не очевидно, что будет делать вызов, и явное лучше, чем неявное в этих случаях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...