ICPO describes how Python resolves a.b: it checks the instance, then its class, then parent classes, and finally object. The search stops at the first matching attribute. section 10.12
Use the lookup order to reason about common object-oriented behaviors:
- Methods are class attributes: s.upper() finds upper on str after failing to find it on the string instance. section 10.12
- Inheritance extends the search: an instance can retrieve a method from a parent class when neither the instance nor its immediate class defines it. section 10.16
- A class attribute remains visible through instances, but assigning through an instance creates an instance attribute that shadows the class attribute. section 10.14
- Prefer self.max_scoops inside shared methods when subclasses should provide different class-level limits. section 10.18
Shared behavior with subclass-specific limits
class Bowl: max_scoops = 3 def add_scoops(self, *new_scoops): if len(self.scoops) + len(new_scoops) <= self.max_scoops: self.scoops.extend(new_scoops) class BigBowl(Bowl): max_scoops = 5 # The same method reads Bowl.max_scoops or BigBowl.max_scoops # through self, depending on the instance. section 10.18
class Employee(Person):
def __init__(self, name, id_number):
super().__init__(name) #1
self.id_number = id_number
Use super().__init__ to invoke the parent initializer when the child initializer must preserve inherited setup. section 10.16

