Lab 03: Descriptor Protocol

Time: 60 minutes | Level: Architect | Docker: docker run -it --rm python:3.11-slim bash

Overview

Descriptors are the mechanism behind Python's property, classmethod, staticmethod, and attribute access. Mastering the descriptor protocol lets you build reusable validation frameworks, ORM-style field definitions, and lazy computed properties.

Step 1: The Descriptor Protocol

A descriptor is any object defining __get__, __set__, or __delete__:

class Descriptor:
    def __get__(self, obj, objtype=None):
        print(f"__get__: obj={obj}, objtype={objtype}")
        return 42
    
    def __set__(self, obj, value):
        print(f"__set__: value={value}")
    
    def __delete__(self, obj):
        print(f"__delete__")

class MyClass:
    attr = Descriptor()

mc = MyClass()
_ = mc.attr       # triggers __get__
mc.attr = 10      # triggers __set__
del mc.attr       # triggers __delete__

# Class-level access
_ = MyClass.attr  # __get__ with obj=None

💡 When accessed on the class (MyClass.attr), obj is None and objtype is MyClass. This lets descriptors return themselves when accessed via the class.

Step 2: Data vs Non-Data Descriptors

💡 Priority order: data descriptors > instance __dict__ > non-data descriptors. property is a data descriptor. Regular functions are non-data descriptors (that's how methods work!).

Step 3: __set_name__ — Automatic Name Binding

📸 Verified Output:

Step 4: Typed Descriptor Validation Framework

📸 Verified Output:

Step 5: property Internals

property is itself implemented as a data descriptor:

Step 6: classmethod and staticmethod as Descriptors

Step 7: __slots__ vs __dict__ Storage

Step 8: Capstone — Full Validation Framework

📸 Verified Output (descriptor validation):

Summary

Concept
Mechanism
Use Case

Data descriptor

__get__ + __set__

Validated attributes

Non-data descriptor

__get__ only

Methods, lazy properties

__set_name__

Called at class creation

Self-naming fields

property internals

Data descriptor

Computed attributes

classmethod

Non-data descriptor with binding

Factory methods

__slots__

Slot descriptors

Memory optimization

Validation framework

TypedDescriptor + validators

ORM/Pydantic-like models

Last updated