Python - Overwriting __getattribute__ for an instance?

This one seems a bit tricky to me. Sometime ago I already managed to overwrite an instance's method with something like:

def my_method(self, attr):
    pass

instancemethod = type(self.method_to_overwrite)
self.method_to_overwrite = instancemethod(my_method, self, self.__class__)

which worked very well for me; but now I'm trying to overwrite an instance's __getattribute__() function, which doesn't work for me for the reason the method seems to be

<type 'method-wrapper'>

Is it possible to do anything about that? I couldn't find any decent Python documentation on method-wrapper.

13.10.2009 15:08:50
4 ОТВЕТА
РЕШЕНИЕ

I believe method-wrapper is a wrapper around a method written in C.

1
13.10.2009 15:25:34

There are a couple of methods which you can't overwrite and __getattribute__() is one of them.

2
14.10.2009 07:36:26
__getattribute__() IS called even when there is attribute with such name. What you said is true for __getattr__() method.
Denis Otkidach 13.10.2009 19:57:03
-1 to Python for the confusion caused by __getattr__, __getattribute__ and __setattr__
John La Rooy 13.10.2009 20:31:03
You're right; I've removed my broken implementation. Ants' solution is correct.
Aaron Digulla 14.10.2009 07:36:54

You want to override the attribute lookup algorithm on an per instance basis? Without knowing why you are trying to do this, I would hazard a guess that there is a cleaner less convoluted way of doing what you need to do. If you really need to then as Aaron said, you'll need to install a redirecting __getattribute__ handler on the class because Python looks up special methods only on the class, ignoring anything defined on the instance.

You also have to be extra careful about not getting into infinite recursion:

class FunkyAttributeLookup(object):
    def __getattribute__(self, key):
        try:
            # Lookup the per instance function via objects attribute lookup
            # to avoid infinite recursion.
            getter = object.__getattribute__(self, 'instance_getattribute')
            return getter(key)
        except AttributeError:
            return object.__getattribute__(self, key)

f = FunkyAttributeLookup()
f.instance_getattribute = lambda attr: attr.upper()
print(f.foo) # FOO

Also, if you are overriding methods on your instance, you don't need to instanciate the method object yourself, you can either use the descriptor protocol on functions that generates the methods or just curry the self argument.

 #descriptor protocol
 self.method_to_overwrite = my_method.__get__(self, type(self))
 # or curry
 from functools import partial
 self.method_to_overwrite = partial(my_method, self)
5
13.10.2009 16:09:21
Didn't know that "Python looks up special methods only on the class, ignoring anything defined on the instance.". Thank you! I wasn't getting any error but it seemed like Python was ignoring me… There should be some kind of exceptions raised? Idk…
jeromej 12.11.2013 14:05:56