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