getting rid of the recursion in __getattribute__

A KR alicpp at gmail.com
Wed May 24 09:37:31 EDT 2023


It is perfectly explained in the standards here [1] saying that: 

<quote>
In order to avoid infinite recursion in this method, its implementation should always call the base class method with the same name to access any attributes it needs, for example, object.__getattribute__(self, name).
</quote>

Therefore, I wrote a code following what the standard says:

<code>
class Sample():
    def __init__(self):
        self.a = -10
        
    def __getattribute__(self, name):
        if name == 'a':
            return object.__getattribute__(self, name)
            
        raise AttributeError()
    
s = Sample()
result = s.a
print(result)
</code>
I did not fall into recursion, and the output was
-10

I used here object.__getattribute__(self, name) cause the base class of Sample is object.

If I derive the Sample class from another class such as A, I should change object.__getattribute__(self, name) to A.__getattribute__(self, name) as the base class of class Sample is class A.

<code>
class A:
    pass

class Sample(A):
    def __init__(self):
        self.a = -10
        
    def __getattribute__(self, name):
        if name == 'a':
            return A.__getattribute__(self, name)
            
        raise AttributeError()
    
s = Sample()

result = s.a
print(result)
</code>
which gives the same output as expected. No recursion and -10.

However, when I try the code without deriving from a class:

class AnyClassNoRelation:
    pass

class Sample():
    def __init__(self):
        self.a = -10
        
    def __getattribute__(self, name):
        if name == 'a':
            return AnyClassNoRelation.__getattribute__(self, name)
            
        raise AttributeError()
    
s = Sample()

result = s.a
print(result)
and calling __getattribute__ via any class (in this example class AnyClassNoRelation) instead of object.__getattribute__(self, name) as the standard says call using the base class, I get the same output: no recursion and -10.

So my question:

How come this is possible (having the same output without using the base class's __getattribute__? Although the standards clearly states that __getattribute__ should be called from the base class.

<quote>
In order to avoid infinite recursion in this method, its implementation should always call the base class method with the same name to access any attributes it needs, for example, object.__getattribute__(self, name). 
</quote>

Literally, I can call __getattribute__ with anyclass (except Sample cause it will be infinite recursion) I define and it works just fine. Could you explain me why that happens?


[1] https://docs.python.org/3/reference/datamodel.html#object.__getattribute__


More information about the Python-list mailing list