Module 5: Descriptors and Class Metaprogramming
Attribute Lookup and Descriptor Precedence
Attribute Lookup and Descriptor Precedence
Attribute access is a protocol, not a simple instance-dictionary lookup. Data descriptors, instance attributes, non-data descriptors, class attributes, the MRO, and __getattr__ participate in a defined precedence.
Module: Module 5: Descriptors and Class Metaprogramming
Core mental model
This lesson is built around four connected ideas. Read them as a decision framework, then prove each one with the walkthrough.
- A data descriptor defines set or delete behavior and outranks the instance dictionary.
- A non-data descriptor defines only get and can be shadowed by an instance attribute.
- Functions on classes are descriptors that produce bound methods.
- __getattr__ is the final missing-attribute fallback.
Walkthrough
class NonData:
def __get__(self, instance, owner):
if instance is None:
return self
return "descriptor value"
class Demo:
value = NonData()
item = Demo()
print(item.value)
item.__dict__["value"] = "instance value"
print(item.value)Because NonData defines only __get__, an instance attribute can shadow it. A property with a setter is a data descriptor and would take precedence. This rule also explains how normal methods bind through function descriptors.
Hands-on lab
Create one data descriptor and one non-data descriptor with the same storage experiment. Trace every step Python takes for reads through the class and an instance.
What to watch for
- Storing per-instance values on the descriptor object shares state accidentally.
- Forgetting the instance is None class-access case breaks introspection.
- Overriding __getattribute__ without delegating can disable descriptor behavior.
Engineering checklist
- Connect the lesson's mental model to the choices made in the walkthrough.
- Test the normal case, an empty or boundary case, and one invalid case.
- Keep external input, side effects, and reusable logic in clearly separated layers.
- Prefer the clearest correct implementation before optimizing or generalizing it.
Completion check
You can implement the lab without copying the example, explain the core concepts in your own words, and show tests or terminal output that demonstrate the expected and failure paths.