Can't define __call__ within __init__?
mnordhoff at mattnordhoff.com
Wed Mar 10 14:58:07 CET 2010
Neal Becker wrote:
> Simon Brunning wrote:
>> On 10 March 2010 13:12, Neal Becker <ndbecker2 at gmail.com> wrote:
>>> Want to switch __call__ behavior. Why doesn't this work? What is the
>>> correct way to write this?
>>> class X (object):
>>> def __init__(self, i):
>>> if i == 0:
>>> def __call__ (self):
>>> return 0
>>> def __call_ (self):
>>> return 1
>>> x = X(0)
>>> TypeError: 'X' object is not callable
>> __call__ is in the __init__ method's local namespace - you need to
>> bind it to the class's namespace instead:
>> X.__call__ = __call__
>> But this probably isn't what you want either, since all instances of X
>> will share the same method.
>> What are you trying to do? In your simple example, you'd be much
>> better off with a single __call__ method. But you knew that.
> Sorry, a bit early in the morning. This works:
> class X (object):
> def __init__(self, i):
> if i == 0:
> def F (self):
> return 0
> def F (self):
> return 1
> self.F = F
> def __call__ (self):
> return self.F (self)
> Not sure if there is a more elegant (or compact) way to write this.
> Could __call__ be defined directly within __init__?
> What I'm trying to do is make a callable whose behavior is switched based on
> some criteria that will be fixed for all calls. In my example, this will
> ultimately be determined by the setting of a command line switch.
ISTM it would be prettiest to do:
def __init__(self, i):
self.flag = i == 0
Or, if the comparison isn't particularly expensive, it would look nicer
to just use self.i and do "self.i == 0" in __call__.
Not that it matters, but this is probably faster than your version, too,
since it saves a method call.
By the way, IIRC Python only looks up double-underscore methods on the
class, not the instance. That's why you had to indirect through self.F.
More information about the Python-list