The descriptor protocol is a fundamental mechanism in Python that governs how attribute access — retrieval, assignment, and deletion — is handled.
It operates through a set of specially defined methods that are implemented in a class, enabling precise control over the behavior of attributes.
These methods, __get__, __set__, and __delete__, are invoked automatically during attribute access operations when a descriptor object
__get__ method when obj.attr is accessed. This overrides the default behavior of retrieving the value directly from the instance's __dict__.
When an attribute is accessed, Python executes a series of well-defined steps to resolve the attribute's value.
Descriptors are typically defined at the class level, meaning they exist as part of the class definition
A descriptor is classified as a data descriptor if it defines the __set__ method or the __delete__ method
data descriptors, by implementing __set__, control both retrieval and assignment of attributes, bypassing the instance’s __dict__.
non-data descriptors, which lack __set__, allow instance attributes to take priority over the descriptor.
This architecture underpins many core Python features, such as property objects and method binding, offering fine-grained control over how attributes behave.