Question presented to candidate:
"What is the descriptor protocol in Python? Explain __get__, __set__ and __set_name__, the difference between a data and a non-data descriptor, and show me a case where you would write one yourself."
What a strong answer should cover:
- A descriptor is an object stored as a class attribute whose type defines
__get__(self, obj, objtype), and optionally__set__(self, obj, value)/__delete__(self, obj); attribute access through an instance then calls those methods. - Data descriptor (has
__set__or__delete__) beats the instance__dict__; non-data descriptor (only__get__) loses to it β and why that matters for caching. __get__receivesobj=Nonewhen accessed on the class, and conventionally returns the descriptor itself;__set_name__(owner, name)(Python 3.6, PEP 487) tells the descriptor the attribute name it was assigned to.- Built-ins are descriptors: functions (binding
selfinto a bound method),property,classmethod,staticmethod,__slots__members,functools.cached_property. - Typical uses: validated or typed fields, ORM columns, lazy/cached attributes; per-instance data must live on the instance (e.g. its
__dict__), not on the shared descriptor.
Code / implementation expected: Yes β a small validating descriptor (for example a Positive field) using __set_name__, __get__ and __set__.