What happens when a __call__ function is defined in both class and object ?

Chris Angelico rosuav at gmail.com
Thu Oct 19 04:26:57 EDT 2017


On Thu, Oct 19, 2017 at 7:24 PM, Chris Angelico <rosuav at gmail.com> wrote:
> On Thu, Oct 19, 2017 at 7:11 PM, ast <nomail at com.invalid> wrote:
>> Hello, please have a look at following code snippet
>> (python 3.4.4)
>>
>> class Test:
>>
>>    a = 1
>>
>>    def __init__(self):
>>        self.a = 2
>>        self.f = lambda : print("f from object")
>>        self.__call__ = lambda : print("__call__ from object")
>>     def __call__(self):
>>        print("__call__ from class Test")
>>     def f(self):
>>        print("f from class Test")
>>
>> test=Test()
>>
>>>>> test.a
>>
>> 2
>> ok, a is defined in both the class and the object, it is read from
>> the object. This is the expected behavior
>>
>>>>> test.f()
>>
>> f from object
>>
>> ok for the same reason
>>
>>>>> test()
>>
>> __call__ from class Test
>>
>>
>> Surprisingly, __call__ from the class is called, not the
>> one defined in the object. Why ?
>
> That's the way most dunder methods (those with "d"ouble "under"scores
> before and after their names) work.

Oops, premature send, sorry!

Dunder methods are looked up on the class. In the extremely rare
situation where you want a per-instance customization, you can do it
yourself with something like this:

class Test:
    def __call__(self):
        if hasattr(self, "spam_handler"):
            return self.spam_handler()
        return generic_spam_handler()

It's more efficient if, most of the time, the instance dict is skipped
and the search starts with the class.

ChrisA



More information about the Python-list mailing list