This article describes how Python looks up an attribute on an object when it executes o.a
. The priority order is interesting - it looks for:
- A class attribute that is a data-descriptor (most commonly a property)
- An instance attribute
- Any other class attribute
We can confirm this using the code below, which creates an object o
with an instance attribute a
, whose class contains a property of the same name:
class C:
def __init__(self):
self.__dict__['a'] = 1
@property
def a(self):
return 2
o = C()
print(o.a) # Prints 2
Why does Python use this priority order rather than the "naive" order (instance attributes take priority over all class attributes)? Python's priority order has a significant drawback: it makes attribute lookups slower, because instead of just returning an attribute of o
if it exists (a common case), Python must first search o
's class and all its superclasses for a data-descriptor.
What is the benefit of Python's priority order? It's presumably not just for the above situation, because having an instance variable and a property of the same name is very much a corner case (note the need to use self.__dict__['a'] = 1
to create the instance attribute, because the usual self.a = 1
would invoke the property).
Is there a different situation in which the "naive" lookup order would cause a problem?
1
:class C { constructor() { Object.defineProperty(this, 'a', {value: 1}); } get a() { return 2; } }
var o = new C(); console.log(o.a);
– Individually__get__
and__set__
) primarily exist to support properties. What I want to know is, why do data descriptors take priority over instance attributes? – Individually__get__
and a__set__
method, I want these hooks to trigger regardless of the detail whether the attribute in question exists in the object's__dict__
or not. Using a non data descriptor is then for the special cases where you want the getter only to trigger if the attribute is not in the__dict__
. Non data descriptors are great for__get__
ting a value once and then caching it in the instance__dict__
, for example. – Pubes