Reputation: 18385
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.
Upvotes: 40
Views: 7597
Reputation: 7855
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:
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:
run()
or doStuff()
or go()
or the ever-popular and ever-redundant doRun()
, you may have a candidate.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.
Upvotes: 48
Reputation: 304355
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.
Upvotes: 4
Reputation: 11315
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.
Upvotes: 0
Reputation: 123732
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.
Upvotes: 0