Understanding Descriptors in Python

Posted by Afsal on 30-Aug-2024

In Python, a descriptor is a powerful feature that allows you to control how attributes of your classes are accessed and modified. Descriptors enable custom behavior when getting, setting, or deleting an attribute, which makes them incredibly useful for implementing properties, method types, and other advanced features. Descriptors are used in django models.py, form.py etc

Key Descriptor Methods

__get__(self, instance, owner)

Called when the attribute is accessed.

instance refers to the object that owns the attribute.

owner refers to the class type of the object.

__set__(self, instance, value)

Called when a value is assigned to the attribute.

value is the new value being assigned.

__delete__(self, instance)

Called when the attribute is deleted using del.

Sample descriptor

class MyDescriptor:

    def __init__(self, name=None):
        self.name = name

    def __get__(self, instance, owner):
        print(f"Getting: {self.name}")
        return instance.__dict__.get(self.name, None)

    def __set__(self, instance, value):
        print(f"Setting: {self.name} to {value}")
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        print(f"Deleting: {self.name}")
        del instance.__dict__[self.name]
class MyClass:
    attribute = MyDescriptor("attribute")

obj = MyClass()
obj.attribute = 42  
print(obj.attribute) 
del obj.attribute

Output

Setting: attribute to 42

Getting: attribute

42

Deleting: attribute

In this example, MyDescriptor is a custom descriptor class that manages the attribute in MyClass. When you set, get, or delete attribute in an instance of MyClass, the corresponding descriptor methods (__set__, __get__, and __delete__) are triggered.

Descriptors are a fundamental part of Python’s data model and offer a clean way to customize access to your class attributes, making your code more robust and flexible.

Why Use Descriptors?

Encapsulation: It hides the internal representation of attributes, allowing you to change it without affecting the external interface.

Validation: You can easily add validation logic to ensure that the attributes always have valid values.

Readability: The code remains clean and readable, adhering to Python's philosophy of simplicity and explicitness.

Reusability: The validation can be re used.

Where you can see this ?

  • Django models
  • Django form
  • Orm 

I hope you have learned something from this post. Please share your valuable suggestions with afsal@parseltongue.co.in