can't rebind magic methods

Alex Martelli aleaxit at yahoo.com
Sat Mar 18 21:04:49 EST 2006


Michael Tobis <mtobis at gmail.com> wrote:

> I'd appreciate an explanation of why this doesn't work and any
> workarounds.

Special methods are looked up (for their automatic use) on the type, not
the instance.  The workaround is therefore to set them on the type, too:

> class myint(object):
> 
>     def __init__(self,val):
>         self.val = int(val)
>         def mystr(self):
>             return self.val.__str__()
>         self.__str__ = new.instancemethod(mystr,self,mint) #doesn't
> work

What you need is to have *** as myint.__str__ *** the method you want to
get called.  If you have a bunch of special methods that you want to
ensure delegate to self.val.(samemethod), you don't have to write them
out -- you can assign them as attributes of myint, with a simple loop of
setattr right after the class statement, or with a custom metaclass, or
whatever you find handiest.

For example (warning, untested code):

def _setdelegate(cls, delegate_cls, name):
    method = getattr(delegate_cls, name)
    def f(self, *a, **k): return method(self.val, *a, **k)
    f.func_name = name
    setattr(cls, name, f)

class myint(object):
    def __init__(self, val):
        self.val = int(val)

for spec in 'str repr hash hex oct'.split():
    _setdelegate(myint, '__%s__' % spec)

This may be worth refactoring into a custom metaclass if you need more
than one class like this myint, but that's quite a side issue.


Alex



More information about the Python-list mailing list