What is a Descriptor?

A descriptor is an object that defines how attribute access works. It implements __get__, __set__, or __delete__ methods.

Basic Descriptor

Create simple descriptor:

class Descriptor:
    def __get__(self, obj, objtype=None):
        return f"Getting value from {obj}"
    
    def __set__(self, obj, value):
        print(f"Setting value to {value}")

class MyClass:
    attr = Descriptor()

obj = MyClass()
obj.attr = 10  # Setting value to 10
print(obj.attr)  # Getting value from...

Property-like Descriptor

Store values:

class ValidatedProperty:
    def __init__(self):
        self._value = None
    
    def __get__(self, obj, objtype=None):
        return self._value
    
    def __set__(self, obj, value):
        if value < 0:
            raise ValueError("Value must be positive")
        self._value = value

class Person:
    age = ValidatedProperty()

person = Person()
person.age = 25  # OK
# person.age = -5  # ValueError

Common Use Cases

  • Validation: Validate values when setting
  • Lazy evaluation: Compute values on access
  • Property implementation: @property uses descriptors
  • ORM frameworks: Database field access

Best Practices

  • Use @property first: Simpler for most cases
  • Use descriptors for reuse: When same logic needed in multiple classes
  • Document behavior: Descriptors can be confusing
  • Test thoroughly: Descriptors affect attribute access

Next Steps

Learn about @property which uses descriptors internally.