Skip to content Skip to sidebar Skip to footer

Cannot Overwrite Implementation For __call__

Take this as an example: class Foo(object): def __init__(self, msg): self._msg = msg def __call__(self): return self._msg foo = Foo('hello') print(foo()) # Print

Solution 1:

When you call an object with (), it executes the __call__ method defined on the object's type. So __call__ is defined on the class Foo, not on your instance foo. If you reassigned Foo.__call__, it would work.

Foo.__call__ = lambda _: 'bye'
print(foo()) # prints 'bye'

Solution 2:

Try this:

class Foo(object):
    def __init__(self, msg):
        self._msg = msg
    def __call__(self):
        return self._msg

foo = Foo('hello')
print(foo()) # Prints 'hello'

Foo.__call__ = lambda _: 'bye' #Notice the capital F, this is the class not the instance
print(foo()) # Prints 'bye'

The last call should print 'bye' like you expect. When you call an instance's functions, it's actually referring to the class functions (where they are defined)


Solution 3:

Typically, you can do this. Override a single instance's implementation of a given method without affecting the rest.

The problem here is that you're attempting to override a "special" method. The () call syntax looks up the __call__ method on the class, not the instance.

The following code shows that you can override a single instance's method implementation, as well as serves as sort of an ugly workaround to your problem:

class Foo(object):
    def __init__(self, msg):
        self._msg = msg
    def __call__(self):
        return self.call()      # Delegate call to instance
    def call(self):
        return self._msg

foo = Foo('hello')
other = Foo('hi')

print(foo()) # Prints 'hello'

def new_call(self):
    return "bye"

foo.call = new_call.__get__(foo, Foo)
print(foo()) # Prints 'bye'

print(other()) # Prints 'hi' (unaffected by override)

Note: the following also would work as you expect:

foo.call = (lambda _: "bye").__get__(foo, Foo)

But I prefer the explicit definition.


Post a Comment for "Cannot Overwrite Implementation For __call__"