The three hooks: __getattribute__, __getattr__, __setattr__
Remove the underscore check in Config.__getattr__ and see what happens in Break it.
Reading obj.name follows a fixed search: data descriptors on the type, then the instance's __dict__, then the class and its parents in MRO order, and only then __getattr__. Methods are plain functions that become bound methods when you read them.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 6 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write a class Lenient with a class attribute shade = "blue" and a __getattr__ that returns "?" for any missing attribute. Print o.shade and o.colour. Then set o.shade = "red", print o.shade and Lenient.shade, delete o.shade and print it again.
Write a class Frozen that accepts x in __init__ but refuses every later assignment by overriding __setattr__. Show that f.x = 4 raises AttributeError.
Using Config from this topic, show that cfg.host works and cfg.timeout raises AttributeError.
Explain it without notes
Describe the order in which Python looks up obj.name.
What is the difference between __getattr__ and __getattribute__?
Why is obj.method is obj.method False?
What happens when you assign obj.x = 5 and the class already has x = 1?
Expected output
__setattr__: real = 1
read real:
__getattribute__: real
1
read missing:
__getattribute__: missing
__getattr__: missing
default-missing
write:
__setattr__: extra = 5
hasattr uses the same path:
__getattribute__: nothing
__getattr__: nothing
True
localhost 8080
AttributeError: no setting 'timeout'