changing __call__ on demand

Steven Bethard steven.bethard at gmail.com
Mon Feb 14 15:37:54 EST 2005


F. Petitjean wrote:
> Le Sun, 13 Feb 2005 13:19:03 -0500, Hans Nowak a écrit :
>>Note that it works just fine if you don't use a new-style class:
>>
>>>>>class Test:
>>
>>...     def __init__(self):
>>...         self.__call__ = self.foobar
>>...     def foobar(self, *args, **kwargs):
>>...         print "Called with:", args, kwargs
>>...
>>
>>>>>t = Test()
>>>>>t()
>>
>>Called with: () {}
>>
>>>>>t(3, 4)
>>
>>Called with: (3, 4) {}
>>
>>>>>t(42, x=0)
>>
>>Called with: (42,) {'x': 0}
> 
> Are you sure that if you add a __call__() method, it will still work
> fine ?

Simple enough to check, isn't it?

py> class C:
...     def __init__(self):
...         self.__call__ = lambda: "__init__"
...     def __call__(self):
...         return "__call__"
...
py> C()()
'__init__'

Old-style classes lookup methods like __call__ on the instance[1]. 
New-style classes look them up on the type:

py> class C:
...     def __init__(self):
...         self.__iter__ = lambda: iter(["__init__"])
...     def __iter__(self):
...         return iter(["__call__"])
...
py> list(C())
['__init__']
py> class C(object):
...     def __init__(self):
...         self.__iter__ = lambda: iter(["__init__"])
...     def __iter__(self):
...         return iter(["__call__"])
...
py> list(C())
['__call__']

AFAICT, non-magic methods are looked up on instance first:

py> class C:
...     def __init__(self):
...         self.f = lambda: "__init__"
...     def f(self):
...         return "__call__"
...
py> C().f()
'__init__'
py> class C(object):
...     def __init__(self):
...         self.f = lambda: "__init__"
...     def f(self):
...         return "__call__"
...
py> C().f()
'__init__'

STeVe

[1] Well, they look there first.



More information about the Python-list mailing list