When is using __call__ a good idea?

I think your intuition is about right.

Historically, callable objects (or what I’ve sometimes heard called “functors”) have been used in the OO world to simulate closures. In C++ they’re frequently indispensable.

However, __call__ has quite a bit of competition in the Python world:

  • A regular named method, whose behavior can sometimes be a lot more easily deduced from the name. Can convert to a bound method, which can be called like a function.
  • A closure, obtained by returning a function that’s defined in a nested block.
  • A lambda, which is a limited but quick way of making a closure.
  • Generators and coroutines, whose bodies hold accumulated state much like a functor can.

I’d say the time to use __call__ is when you’re not better served by one of the options above. Check the following criteria, perhaps:

  • Your object has state.
  • There is a clear “primary” behavior for your class that’s kind of silly to name. E.g. if you find yourself writing run() or doStuff() or go() or the ever-popular and ever-redundant doRun(), you may have a candidate.
  • Your object has state that exceeds what would be expected of a generator function.
  • Your object wraps, emulates, or abstracts the concept of a function.
  • Your object has other auxilliary methods that conceptually belong with your primary behavior.

One example I like is UI command objects. Designed so that their primary task is to execute the comnand, but with extra methods to control their display as a menu item, for example, this seems to me to be the sort of thing you’d still want a callable object for.

Leave a Comment