Can't define __call__ within __init__?

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Wed Mar 10 22:18:47 EST 2010


On Wed, 10 Mar 2010 08:12:14 -0500, Neal Becker 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
>         else:
>             def __call_ (self):
>                 return 1


Others have already pointed out that there are two reasons that won't 
work: 

(1) you define __call__ as a local variable of the __init__ method which 
then disappears as soon as the __init__ method completes; and

(2) special methods like __call__ are only called on the class, not the 
instance, so you can't give each instance its own method.


Perhaps the best way to solve this is to use delegation:


def zero_returner():
    return 0

def one_returner():
    return 1


class X (object):
    def __init__(self, i):
        if i == 0:
            self.func = zero_returner
        else:
            self.func = one_returner
    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs)


zero_returner and one_returner can be any callable object, not 
necessarily a function.

Of course, all this assumes that your solution isn't even simpler:

class X (object):
    def __init__(self, i):
        self.i = i
    def __call__(self):
        return self.i

but I assume if it was that simple, you would have done that already.



-- 
Steven



More information about the Python-list mailing list