Python › Descriptors & Properties

How do you write a descriptor that behaves differently when accessed on the CLASS itself versus on an INSTANCE?

Advanced

Answer

__get__(self, instance, owner) receives 'instance' as None when accessed via the CLASS (e.g., MyClass.attr) rather than an instance (e.g., my_obj.attr) — checking `if instance is None` inside __get__ lets you return something different (often the descriptor itself, matching @property's own convention) for class-level access.
class Descriptor:
    def __get__(self, instance, owner):
        if instance is None:
            return self  # accessed via the class itself: return the descriptor
        return f"Value for {instance}"

class Example:
    attr = Descriptor()

print(Example.attr)          # <Descriptor object> -- instance is None here
print(Example().attr)        # "Value for <Example object>" -- instance is set
Real-world example Building a descriptor (like an ORM field definition) that exposes metadata when accessed via the class, but returns actual data via an instance.

Common follow-ups: How does Django's ORM use exactly this class-vs-instance distinction to let Model.field_name work for QUERYING?