According to Python's documentation,
Data descriptors with
__set__()
and__get__()
defined always override a redefinition in an instance dictionary.
I have no problem understanding this sentence, but can someone clarify for me why such a rule is in place? After all, if I want to override an attribute in an instance dictionary, I already need to do that explicitely (inst.__dict__["attr"] = val
), as a naive inst.attr = val
would call the descriptor's __set__
method, which would (usually) not override the attribute in the instance dictionary.
edit: just to make it clear, I understand what is happening, my question is about why such a rule was put in place.
The override applies to descriptors that are part of the class
__dict__
.Python will always look up
type(instance).__dict__[attributename].__get__(instance, type(instance))
, and will not useinstance.__dict__
to search for a instance-override.Here is an example using a contrived
Descriptor
class and a property (which is a descriptor with a__get__
and a__set__
:As you can see, even though I add a
spam
entry in the instance__dict__
, it is completely ignored and theFoo.spam
property is used still. Python is ignoring the instance__dict__
because thespam
property defines both__get__
and a__set__
.If you use a descriptor that doesn't define a
__set__
the override works (but it's__get__
is not called: