0

If I have the following class:

class Item:
    def __getattribute__(self, a):
        return super().__getattribute__(a)
    def __getattr__(self, a):
        print ("Calling the second one (AttributeError on __getattribute__)!")

Now if I do something like:

i=Item()
i.x

It will hit an AttributeError in __getattribute__ and fall back to __getattr__. What is the point of having such a fallback? For example, why couldn't someone just customize the __getattribute__ method itself if an AttributeError is reached? What would be a legitimate use case of defining a __getattr__ / __getattribute__ pair?

David542
  • 104,438
  • 178
  • 489
  • 842
  • This is truly strange, behaviour although possibly a duplication of this question: https://stackoverflow.com/questions/3278077/difference-between-getattr-vs-getattribute – Nick Martin Oct 18 '19 at 01:17

1 Answers1

2

This is the way it is for historical reasons. __getattr__ was the only method of the two to exist in the obsolete "old-style" class system. __getattribute__ came later, but they couldn't take out __getattr__, because it would have broken a lot of code, as well as causing problems for mixing the old-style and new-style class systems.

It's slightly more convenient to be able to define a __getattr__ instead of overriding __getattribute__ when you want your logic to be a fallback for the default logic, but it's extremely unlikely that that would have been enough to motivate the inclusion of __getattr__ in the language if __getattribute__ had existed from the start.

user2357112
  • 260,549
  • 28
  • 431
  • 505