__getattr__ vs __getattribute__ in Python
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! :)