Descriptors are objects with method __get__
, __set__
, and __del__
. These when used as class attributes, they add the behavior to the attribute that gets triggered when they accessed.
For example,
class DefaultAge:
def __get__(self, obj, objtype=None):
return 12
class Person:
age = DefaultAge()
We access age
attribute on Person
class, python triggers __get__
method of descriptor.
>>> Person.age
12
How it works?
When python encounters a descriptor as a class attribute, the invocation happens like below,
Person.__dict__['age'].__get__(None, Person)
This also explains __get__
parameters where self
is the descriptor itself, obj
is the class instance (explained in subsequent section) and objtype
which is class.
If we can Person instance and then try to access age
attribute,
>>> person = Person()
>>> person.age
12
the invocation happens like below,
type(person).__dict__['age'].__get__(person, type(person))
Use cases
Most common use cases of descriptors are classmethod
, staticmethod
, property
.
Refer this notebook which contains custom implementations for classmethod
and staticmethod
.