The descriptor protocol allows user programmable attribute access. The descriptor protocol is what enables class methods, static methods, properties and super().

Descriptor objects are class attributes which control the behavior of instance attributes. Consequently, a single descriptor is common to all instances of a class and should not be mutated when instance attributes are accessed.

Do not mutate the descriptor object, rather create a new object that contains the necessary state.

In this example the descriptor class MutatingDescriptor stores a reference to obj in an attribute.

In the following example, the descriptor class NonMutatingDescriptor returns a new object every time __get__ is called.

  • Python Language Reference: Implementing Descriptors.
  • Mark Lutz. Learning Python, Section 30.6: Methods Are Objects: Bound or Unbound. O'Reilly 2013.
  • A real world example: NumPy Issue 5247.