getattr VS getattribute
Python data model contains two methods with similar names:
__getattr__ and __getattribute__.
The key difference is that __getattribute__ is called unconditionally
on an every attribute access,
but __getattr__ is only called when __getattribute__ fails
to find an attribute (raises AttributeError).
The default __getattribute__ behavior (the one you use every day)
is to return the attribute if it exists or to raise AttributeError.
There are no default for __getattr__.
That actually means that by default __getattr__ is a way to handle attributes
that couldn't be found by ordinary means.
That can be helpful for some sorts of metaprogramming or creating DSLs.
With this code you can get hex version of any attribute
by prepending hex_ to its name
(that's not really helpful but good enough as an example):
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
@property
def x(self):
return self._x
@property
def y(self):
return self._y
def __getattr__(self, attr):
prefix, orig_attr = attr.split('_', 2)
if prefix == 'hex' and hasattr(self, orig_attr):
return hex(getattr(self, orig_attr))
else:
raise AttributeError
p = Point(16, 20)
print(p.hex_x, p.hex_y)
There are also __setattr__ and __delattr__ methods for setting and deleting attributes, and they both are called unconditionally. That means that the __getattr__ method stands out here, not __getattrbiute__ like it may seem.