Search code examples
pythonclassgetattr

How do I implement __getattribute__ without an infinite recursion error?


I want to override access to one variable in a class, but return all others normally. How do I accomplish this with __getattribute__?

I tried the following (which should also illustrate what I'm trying to do) but I get a recursion error:

class D(object):
    def __init__(self):
        self.test=20
        self.test2=21
    def __getattribute__(self,name):
        if name=='test':
            return 0.
        else:
            return self.__dict__[name]

>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp

Solution

  • You get a recursion error because your attempt to access the self.__dict__ attribute inside __getattribute__ invokes your __getattribute__ again. If you use object's __getattribute__ instead, it works:

    class D(object):
        def __init__(self):
            self.test=20
            self.test2=21
        def __getattribute__(self,name):
            if name=='test':
                return 0.
            else:
                return object.__getattribute__(self, name)
    

    This works because object (in this example) is the base class. By calling the base version of __getattribute__ you avoid the recursive hell you were in before.

    Ipython output with code in foo.py:

    In [1]: from foo import *
    
    In [2]: d = D()
    
    In [3]: d.test
    Out[3]: 0.0
    
    In [4]: d.test2
    Out[4]: 21
    

    Update:

    There's something in the section titled More attribute access for new-style classes in the current documentation, where they recommend doing exactly this to avoid the infinite recursion.