In the example below, attribute x is accessed from the slots of the object even though x is present in __dict__ (this is not a typical or probably useful case, but I'm curious):
>>> class C(object):
... __slots__ = 'x'
...
>>> class D(C):
... pass
...
>>> obj = D()
>>> obj.x = 'Stored in slots'
>>> obj.__dict__
{}
>>> obj.__dict__['x'] = 'stored in __dict__'
>>> obj.x
'Stored in slots'
Is this order of access (slots first) a documented behavior? or simply an implementation detail?
Yes, the __dict__ of an object is only consulted after data descriptors have been consulted. __slots__ attributes are implemented as data descriptors.
See Invoking descriptors:
For instance bindings, the precedence of descriptor invocation depends on the which descriptor methods are defined. A descriptor can define any combination of
__get__(),__set__()and__delete__(). If it does not define__get__(), then accessing the attribute will return the descriptor object itself unless there is a value in the object’s instance dictionary. If the descriptor defines__set__()and/or__delete__(), it is a data descriptor; if it defines neither, it is a non-data descriptor. Normally, data descriptors define both__get__()and__set__(), while non-data descriptors have just the__get__()method. Data descriptors with__set__()and__get__()defined always override a redefinition in an instance dictionary. In contrast, non-data descriptors can be overridden by instances.
and from the same page, section on slots:
__slots__are implemented at the class level by creating descriptors (Implementing Descriptors) for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by__slots__; otherwise, the class attribute would overwrite the descriptor assignment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With