137. Implementing Custom Descriptors

Descriptors in Python are a way to manage the behavior of attributes in classes. They allow you to define how attributes are accessed, modified, or deleted in a class. A descriptor is any object that implements any of the following methods:

  • __get__(self, instance, owner)

  • __set__(self, instance, value)

  • __delete__(self, instance)

Here are 10 Python code snippets that demonstrate different use cases for implementing custom descriptors:

1. Basic Descriptor Example

A simple descriptor that manages the access of an attribute.

class MyDescriptor:
    def __get__(self, instance, owner):
        return f"Getting attribute from {owner}"

    def __set__(self, instance, value):
        print(f"Setting attribute to {value}")

    def __delete__(self, instance):
        print("Deleting attribute")

class MyClass:
    attr = MyDescriptor()

# Example usage
obj = MyClass()
obj.attr = 10
print(obj.attr)
del obj.attr

Explanation:

  • __get__: Defines behavior when accessing the attribute.

  • __set__: Defines behavior when assigning a value to the attribute.

  • __delete__: Defines behavior when deleting the attribute.


2. Read-Only Descriptor

A descriptor that prevents modifying an attribute after it has been set.

Explanation:

  • The attribute is read-only because the __set__ method raises an error when trying to modify it.


3. Logging Access to Attributes

A descriptor that logs every access to the attribute.

Explanation:

  • __set_name__: Sets the attribute name.

  • The __get__ and __set__ methods print logs when the attribute is accessed or modified.


4. Property-Like Descriptor

A descriptor that works like a property but with custom logic for getting, setting, and deleting.

Explanation:

  • MyProperty acts like a property but gives you full control over the getter and setter methods.


5. Validating Attribute Values with Descriptors

A descriptor that validates the value before allowing it to be set.

Explanation:

  • The IntegerDescriptor validates that the attribute value is an integer before setting it.


6. Descriptor with Default Values

A descriptor that provides a default value if the attribute is not set.

Explanation:

  • DefaultDescriptor provides a default value when the attribute is accessed before being set.


7. Type-Checking Descriptor

A descriptor that ensures the value matches a specified type.

Explanation:

  • TypeCheckingDescriptor ensures that only values of a specified type can be assigned to the attribute.


8. Deleting an Attribute via Descriptor

A descriptor that defines custom behavior when an attribute is deleted.

Explanation:

  • __delete__: Custom logic is defined for deleting the attribute.


9. Lazy-Loading Attribute

A descriptor that loads an attribute value only when it's needed (lazy loading).

Explanation:

  • The attribute is loaded only when it is accessed for the first time.


10. Counter Attribute Descriptor

A descriptor that keeps track of how many times an attribute has been accessed.

Explanation:

  • CounterDescriptor tracks how many times the attribute has been accessed.


These snippets showcase the flexibility and power of descriptors in Python. Descriptors can be used for a wide variety of purposes, such as enforcing rules on attribute values, adding custom behavior to attribute access, and more.

Last updated