Difference between __getattr__ and __getattribute__
A key difference between __getattr__
and __getattribute__
is that __getattr__
is only invoked if the attribute wasn't found the usual ways. It's good for implementing a fallback for missing attributes, and is probably the one of two you want.
__getattribute__
is invoked before looking at the actual attributes on the object, and so can be tricky to implement correctly. You can end up in infinite recursions very easily.
New-style classes derive from object
, old-style classes are those in Python 2.x with no explicit base class. But the distinction between old-style and new-style classes is not the important one when choosing between __getattr__
and __getattribute__
.
You almost certainly want __getattr__
.
Understanding the difference between __getattr__ and __getattribute__
Some basics first.
With objects, you need to deal with their attributes. Ordinarily, we do instance.attribute
. Sometimes we need more control (when we do not know the name of the attribute in advance).
For example, instance.attribute
would become getattr(instance, attribute_name)
. Using this model, we can get the attribute by supplying the attribute_name as a string.
Use of __getattr__
You can also tell a class how to deal with attributes which it doesn't explicitly manage and do that via __getattr__
method.
Python will call this method whenever you request an attribute that hasn't already been defined, so you can define what to do with it.
A classic use case:
class A(dict):
def __getattr__(self, name):
return self[name]
a = A()
# Now a.somekey will give a['somekey']
Caveats and use of __getattribute__
If you need to catch every attribute regardless whether it exists or not, use __getattribute__
instead. The difference is that __getattr__
only gets called for attributes that don't actually exist. If you set an attribute directly, referencing that attribute will retrieve it without calling __getattr__
.
__getattribute__
is called all the times.
Some questions about __getattr__ and __getattribute__?
The __getattribute__
, __setattr__
and __delattr__
methods are called for all attribute access (getting, setting and deleting). __getattr__
on the other hand is only called for missing attributes; it is not normally already implemented, but if it is then __getattribute__
calls it if it could not otherwise locate the attribute, or if an AttributeError
was raised by __getattribute__
.
You replaced the standard implementations of the 3 main methods with methods that do nothing but print and return None
(the default in the absence of an explicit return
statement). __dict__
is just another attribute access, and your __getattribute__
method returns None
, and never itself calls __getattr__
or raises an AttributeError
.
From the Customizing attribute access documentation:
object.__getattr__(self, name)
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree forself
).
and
object.__getattribute__(self, name)
Called unconditionally to implement attribute accesses for instances of the class. If the class also defines__getattr__()
, the latter will not be called unless__getattribute__()
either calls it explicitly or raises anAttributeError
.
(Bold emphasis mine).
Either call the base implementation (via super().__getattribute__
) or raise an AttributeError
:
>>> class B:
... def __init__(self):
... self.name = '234'
... def __getattribute__(self, name):
... print('getattr')
... return super().__getattribute__(name)
... def __getattr__(self, name):
... print('get')
... def __setattr__(self, name, value):
... print('set')
... def __delattr__(self, name):
... print('del')
...
>>> b = B()
set
>>> b.__dict__
getattr
{}
>>> b.name
getattr
get
>>> class B:
... def __init__(self):
... self.name = '234'
... def __getattribute__(self, name):
... print('getattr')
... raise AttributeError(name)
... def __getattr__(self, name):
... print('get')
... def __setattr__(self, name, value):
... print('set')
... def __delattr__(self, name):
... print('del')
...
>>> b = B()
set
>>> b.__dict__
getattr
get
>>> b.name
getattr
get
Note that by calling super().__getattribute__
the actual __dict__
attribute is found. By raising an AttributeError
instead, __getattr__
was called, which also returned None
.
What is the difference between type.__getattribute__ and object.__getattribute__?
You are operating directly on classes. object.__getattribute__
is only used on instances of A
and B
instead. That's because special methods are looked up on the type; for instances the type is the class.
For classes then, the type is.. type
:
>>> class A:
... f = 1
...
>>> class B(A):
... pass
...
>>> type(B)
<class 'type'>
so type.__getattribute__
is used:
>>> type.__getattribute__(B, 'f')
1
and object.__getattribute__
works fine on instances:
>>> object.__getattribute__(B(), 'f')
1
For instances attributes are looked up first on the class (in the case of data descriptors), then on the instance, then if the instance doesn't have the attribute, the class hierarchy is searched in MRO order. This is the job of object.__getattribute__
. So object.__getattribute__
looks at the first argument (e.g. self
, the instance object) for the attribute, and at objects in type(self).__mro__
.
For classes, attributes are looked up on the class itself and all its bases; type.__getattribute__
looks directly at self.__mro__
for these; self
being a class object here.
If you use object.__getattribute__
for classes then, there is no f
attribute on B
directly, and no f
anywhere in type(B).__mro__
. If you use type.__getattribute__
, A
is a member of B.__mro__
so f
is found there:
>>> type(B).__mro__
(<class 'type'>, <class 'object'>)
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
Difference between __getattribute__ and obj.__dict__['x'] in python?
__getattribute__()
method is for lower level attribute processing.
Default implementation tries to find the name
in the internal __dict__
(or __slots__
). If the attribute is not found, it calls __getattr__()
.
UPDATE (as in the comment):
They are different ways for finding attributes in the Python data model. They are internal methods designed to fallback properly in any possible situation. A clue: "The machinery is in object.__getattribute__()
which transforms b.x
into type(b).__dict__['x'].__get__(b, type(b))
." from docs.python.org/3/howto/descriptor.html
What is the relationship between __getattr__ and getattr?
Alex's answer was good, but providing you with a sample code since you asked for it :)
class foo:
def __init__(self):
self.a = "a"
def __getattr__(self, attribute):
return "You asked for %s, but I'm giving you default" % attribute
>>> bar = foo()
>>> bar.a
'a'
>>> bar.b
"You asked for b, but I'm giving you default"
>>> getattr(bar, "a")
'a'
>>> getattr(bar, "b")
"You asked for b, but I'm giving you default"
So in short answer is
You use
__getattr__
to define how to handle attributes that are not found
and
getattr
to get the attributes
What are some rules of thumb for deciding between __get__, __getattr__, and __getattribute__?
__setattribute__
does not exist because __setattr__
is always called. __getattr__
is only called for f.x
if the attribute lookup fails via the normal channel (which is provided by __getattribute__
, so that function is similarly always called).
The descriptor protocol is slightly orthogonal to the others. Given
class Foo(object):
def __init__(self):
self.x = 5
f = Foo()
The following are true:
f.x
would invokef.__getattribute__('x')
if it were defined.f.x
would not invokef.__getattr__('x')
if it were defined.f.y
would invokef.__getattr__('y')
if it were defined, or else
f.__getattribute__('y')
if it were defined.
The descriptor is invoked by an attribute, rather than for an attribute. That is:
class MyDescriptor(object):
def __get__(...):
pass
def __set__(...):
pass
class Foo(object):
x = MyDescriptor()
f = Foo()
Now, f.x
would cause type(f).__dict__['x'].__get__
to be called, and f.x = 3
would call type(f).__dict__['x'].__set__(3)
.
That is, Foo.__getattr__
and Foo.__getattribute__
would be used to find what f.x
references; once you have that, f.x
produces the result of type(f.x).__get__()
if defined, and f.x = y
invokes f.x.__set__(y)
if defined.
(The above calls to __get__
and __set__
are only approximately correct, since I've left out the details of what arguments __get__
and __set__
actually receive, but this should be enough to explain the difference between __get__
and __getattr[ibute]__
.)
Put yet another way, if MyDescriptor
did not define __get__
, then f.x
would simply return the instance of MyDescriptor
.
Related Topics
How to Compare Version Numbers in Python
How to Check If a Float Value Is a Whole Number
Elegant Python Code for Integer Partitioning
Can You Add New Statements to Python's Syntax
Calculating a Directory's Size Using Python
Convert Array of Indices to One-Hot Encoded Array in Numpy
How to Create a Copy of an Object in Python
How to Display Pandas Dataframe of Floats Using a Format String for Columns
How to Select Rows in a Dataframe Between Two Values, in Python Pandas
In Pandas, Is Inplace = True Considered Harmful, or Not
How to Have Clusters of Stacked Bars
How to Draw Vertical Lines on a Given Plot
What's the Fastest Way of Checking If a Point Is Inside a Polygon in Python
How to Detach Matplotlib Plots So That the Computation Can Continue