When is using __call__ a good idea?

Question:

What are peoples’ opinions on using the __call__. I’ve only very rarely seen it used, but I think it’s a very handy tool to use when you know that a class is going to be used for some default behaviour.

Asked By: Tim McNamara

||

Answers:

Use it if you need your objects to be callable, that’s what it’s there for

I’m not sure what you mean by default behaviour

One place I have found it particularly useful is when using a wrapper or somesuch where the object is called deep inside some framework/library.

Answered By: John La Rooy

More generally, Python has a lot of double-underscore methods. They’re there for a reason: they are the Python way of overloading operators. For instance, if you want a new class in which addition, I don’t know, prints "foo", you define the __add__ and __radd__ methods. There’s nothing inherently good or bad about this, any more than there’s anything good or bad about using for loops.

In fact, using __call__ is often the more Pythonic approach, because it encourages clarity of code. You could replace MyCalculator.calculateValues( foo ) with MyCalculator( foo ), say.

Answered By: Katriel

Its usually used when class is used as function with some instance context, like some DecoratorClass which would be used as @DecoratorClass('some param'), so ‘some param’ would be stored in the instance’s namespace and then instance being called as actual decorator.

It is not very useful when your class provides some different methods, since its usually not obvious what would the call do, and explicit is better than implicit in these cases.

Answered By: Daniel Kluev

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.

Answered By: Owen S.
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.