[Python-Dev] Dinamically set __call__ method
Nathaniel Smith
njs at pobox.com
Tue Nov 4 19:22:12 CET 2014
On Tue, Nov 4, 2014 at 4:52 PM, Roberto Martínez
<robertomartinezp at gmail.com> wrote:
> Hi folks,
>
> I am trying to replace dinamically the __call__ method of an object using
> setattr.
> Example:
>
> $ cat testcall.py
> class A:
> def __init__(self):
> setattr(self, '__call__', self.newcall)
>
> def __call__(self):
> print("OLD")
>
> def newcall(self):
> print("NEW")
>
> a=A()
> a()
>
> I expect to get "NEW" instead of "OLD", but in Python 3.4 I get "OLD".
>
> $ python2.7 testcall.py
> NEW
> $ python3.4 testcall.py
> OLD
>
> I have a few questions:
>
> - Is this an expected behavior?
> - Is possible to replace __call__ dinamically in Python 3? How?
For new-style classes, special methods like __call__ are looked up
directly on the class, not on the object itself. If you want to change
the result of doing a(), then you need to reassign A.__call__, not
a.__call__.
In python 3, all classes are new-style classes. In python 2, only
classes that inherit from 'object' are new-style classes. (If you
replace 'class A:' with 'class A(object):' then you'll see the same
behaviour on both py2 and py3.)
Easy workaround:
def __call__(self, *args, **kwargs):
return self._my_call(*args, **kwargs)
Now you can assign a._my_call to be whatever you want.
-n
--
Nathaniel J. Smith
Postdoctoral researcher - Informatics - University of Edinburgh
http://vorpus.org
More information about the Python-Dev
mailing list