Skip to content

Descriptors and Attribute Magic

Beginning of the lesson

Descriptors and Attribute Magic

Take control of what obj.attr really does

Big Idea: Every time you write obj.attr, Python runs a small algorithm to decide where that value comes from. Three mechanisms let you reshape that algorithm: the descriptor protocol (__get__/__set__/__delete__) attaches reusable get/set logic to a class attribute; __getattr__ and __getattribute__ intercept lookups on an instance; and __slots__ replaces the per-instance __dict__ with a fixed, compact layout. Master these and you understand how property, classmethod, ORMs and dataclasses are built.
By the end you will be able to:
  • trace the exact order Python uses to resolve obj.attr,
  • write a reusable descriptor with __get__, __set__ and __set_name__,
  • distinguish data from non-data descriptors and predict which wins over the instance dict,
  • use __getattr__ for fallbacks and know why __getattribute__ is a loaded gun,
  • apply __slots__ to cut memory and lock down attributes, with its trade-offs.

1. What really happens on obj.attr

Attribute access is not a simple dictionary lookup. Reading obj.attr calls type(obj).__getattribute__(obj, "attr"), and the default implementation on object follows a precise order. Understanding that order is the whole foundation of this topic.

  1. Python walks the type's MRO (method resolution order) looking for attr. If it finds a class attribute that is a data descriptor (defines __set__ or __delete__), that descriptor wins immediately and its __get__ runs.
  2. Otherwise Python checks the instance's own __dict__. If attr is there, that value is returned.
  3. Otherwise, back to the class attribute found on the MRO: if it is a non-data descriptor (only __get__) or a plain value, that is used.
  4. If nothing was found, Python calls __getattr__ as a last-resort hook. If that too is absent, AttributeError is raised.

The single most important consequence: a data descriptor on the class beats the instance dict, but a non-data descriptor loses to the instance dict. That one rule explains most "why did my attribute do that?" surprises.

Continue this lesson on YourAIZone

The full lesson has the complete explanation, worked examples, common mistakes, tests with instant checking and an AI tutor. Start right away as a guest, or create an account to keep your progress.

In the full lesson

  • The complete explanation
  • Worked examples
  • Common mistakes and how to avoid them
  • Test questions: 15
  • AI tutor that answers questions about the topic
  • Progress tracking for students, parents and teachers