RNanoware
RNanoware

Reputation: 581

How does object.__getattribute__ avoid a RuntimeError?

In the rare cases that an object's __getattribute__ method must be overridden, a common mistake is to try and return the attribute in question like so:

class WrongWay:
    def __getattribute__(self, name):
        # Custom functionality goes here
        return self.__dict__[name]

This code always yields a RuntimeError due to a recursive loop, since self.__dict__ is in itself an attribute reference that calls upon the same __getattribute__ method.

According to this answer, the correct solution to this problem is to replace last line with:

...
        return super().__getattribute__(self, name) # Defer responsibility to the superclass

This solution works when run through the Python 3 interpreter, but it also seems to violate __getattribute__'s promised functionality. Even if the superclass chain is traversed up to object, at the end of the line somebody will eventually have to return self.something, and by definition that attribute reference must first get through the child's __getattribute__ method.

How does Python get around this recursion issue? In object.__getattribute__, how is anything returned without looping into another request?

Upvotes: 2

Views: 272

Answers (1)

user2357112
user2357112

Reputation: 280181

at the end of the line somebody will eventually have to return self.something, and by definition that attribute reference must first get through the child's __getattribute__() method.

That's not correct. object.__getattribute__ is not defined as returning self.anything, and it does not respect descendant class implementations of __getattribute__. object.__getattribute__ is the default attribute access implementation, and it always performs its job through the default attribute access mechanism.

Similarly, object.__eq__ is not defined as returning self == other_thing, and it does not respect descendant class implementations of __eq__. object.__str__ is not defined as returning str(self), and it does not respect descendant class implementations of __str__. object's methods are the default implementations of those methods, and they always do the default thing.

Upvotes: 2

Related Questions