Command Palette

Search for a command to run...

Hectal
Back to the lesson: Topic 13.4 — How Attribute Lookup Works
Python · Example 1 of 3

Lookup order, shadowing and bound methods

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.

01

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.

02

Write a class Frozen that accepts x in __init__ but refuses every later assignment by overriding __setattr__. Show that f.x = 4 raises AttributeError.

03

Using Config from this topic, show that cfg.host works and cfg.timeout raises AttributeError.

Explain it without notes

01

Describe the order in which Python looks up obj.name.

02

What is the difference between __getattr__ and __getattribute__?

03

Why is obj.method is obj.method False?

04

What happens when you assign obj.x = 5 and the class already has x = 1?

Lookup order, shadowing and bound methods
Sign in to run this example in your browser.

Expected output

instance dict: {'name': 'Rex'}
name  -> Rex (found in the instance dict)
legs  -> 4 (not on the instance or Dog, found on Animal)
MRO   -> ['Dog', 'Animal', 'object']
after d.legs = 3: 3 4 {'name': 'Rex', 'legs': 3}
bound method is new each time: False
but they are equal: True
underlying function is shared: True
bound to: True
called by hand: Woof == Woof