__getattr__ vs __getattribute__ in Python

Photo by Nigel Tadyanehondo on Unsplash

in Python, what’s the difference between

__getattr__ , __getattribute__ , and getattr() ?

__getattr__

__getattr__ gets called if there is no attribute in the instance.

It’s invoked “last”, if Python can’t find that attribute.(lowest priority)

__getattribute__

__getattribute__ gets called all the times, whether there is the attribute or not.

It’s invoked “first”(highest priority) — it actually “intercepts” every lookup.

So, even if there is the attribute in the instance, Python calls __getattribute__ first, with the attribute as an argument.

getattr()

getattr() has 2 or 3 parameters.

getattr(myObj, ‘myAttribute’) is the same as myObj.myAttribute. Here, the second argument is a string.

In getattr(myObj, ‘anotherAttribute’, ‘myDefault’), the 3rd argument is a default value. So, if there is no attribute ‘anotherAttribute’, then the 3rd argument ‘myDefault’ is returned.

Code Example

All right. let’s look through some simple examples.

class A:    def __getattr__(self, name):        return ('hahaha-'+name)
a = A()
a.ace = 'ace value'
print(a.ace)
print(a.ace2)print(a.__dict__)

The result is:

ace valuehahaha-ace2{‘ace’: ‘ace value’}
  • Python could find ‘ace’, so it prints the value of ‘ace’.
  • But, ‘ace2’ cannot be found, so __getattr__ is invoked.
  • if we print a.__dict__out, we can see the attribute ‘ace’ and the value of it.

What if we add __getattribute__ at class A?

class A:    def __getattr__(self, name):        return (‘hahaha-’+name)    def __getattribute__(self,name):        return (‘jajaja-’+name)
a = A()
a.ace = ‘ace value’
print(a.ace)
print(a.ace2)print(a.__dict__)

The result is:

jajaja-acejajaja-ace2jajaja-__dict__
  • Even though we assigned a value ‘ace value’ to the attribute ‘ace’, __getattribute__ is invoked first(It “intercepts” every lookup). Python doesn’t even try to find ‘ace’.
  • ‘ace2’ does not exist. __getattribute__ is also called here, not __getattr__ .
  • If we see the output of a.__dict__, we again can conclude that __getattribute__ is invoked “first”, the highest priority.

In short:

  • __getattribute__ gets called “first”(the highest priority), whether or not there’s the attribute.
  • __getattr__ gets called “last”(the lowest priority), if Python cannot find the attribute.

Thanks! :)

Happy coding, enjoy learning :)