Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between type.__getattribute__ and object.__getattribute__?

Given:

In [37]: class A:
   ....:     f = 1
   ....:

In [38]: class B(A):
   ....:     pass
   ....:

In [39]: getattr(B, 'f')
Out[39]: 1

Okay, that either calls super or crawls the mro?

In [40]: getattr(A, 'f')
Out[40]: 1

This is expected.

In [41]: object.__getattribute__(A, 'f')
Out[41]: 1

In [42]: object.__getattribute__(B, 'f')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-42-de76df798d1d> in <module>()
----> 1 object.__getattribute__(B, 'f')

AttributeError: 'type' object has no attribute 'f'

What is getattribute not doing that getattr does?

In [43]: type.__getattribute__(B, 'f')
Out[43]: 1

What?! type.__getattribute__ calls super but object's version doesn't?

In [44]: type.__getattribute__(A, 'f')
Out[44]: 1
like image 502
Neil G Avatar asked Jun 10 '14 21:06

Neil G


People also ask

What is __ Getattribute __?

__getattribute__This method should return the (computed) attribute value or raise an AttributeError exception. In order to avoid infinite recursion in this method, its implementation should always call the base class method with the same name to access any attributes it needs, for example, object.

What is Getattribute in Python?

Python getattr() function is used to get the value of an object's attribute and if no attribute of that object is found, default value is returned. Basically, returning the default value is the main reason why you may need to use Python getattr() function.

What is the __ dict __ attribute of an object in Python?

A special attribute of every module is __dict__. This is the dictionary containing the module's symbol table. A dictionary or other mapping object used to store an object's (writable) attributes.

What is Getattr and Setattr in Python?

Python setattr() and getattr() goes hand-in-hand. As we have already seen what getattr() does; The setattr() function is used to assign a new value to an object/instance attribute. Syntax. Use a different Browser.


1 Answers

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'>)
like image 104
Martijn Pieters Avatar answered Oct 10 '22 04:10

Martijn Pieters