How does inheritance work for Attributes?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Inheritance lets a subclass reuse attributes and methods defined by a parent class, but the exact behavior depends on whether you are dealing with instance attributes or class attributes. In Python-style OOP, that distinction is the key to understanding how attribute lookup really works.
Attribute Lookup Starts At The Instance
When you access obj.name, Python does not jump straight to the parent class. It follows a lookup path:
- check the instance itself
- check the class
- check parent classes according to the method resolution order
A small example makes this concrete.
d.name comes from the instance attribute set in Animal.__init__. d.species comes from the class attribute defined on Animal and inherited through Dog.
Instance Attributes Are Usually Created Per Object
Instance attributes are typically assigned in __init__.
Here the Car instance gets:
- '
makeandmodelfrom the parent initializer' - '
seatsfrom the subclass initializer'
That is the normal way subclasses inherit and extend instance state.
Class Attributes Are Shared Until Overridden
Class attributes live on the class object and are shared by instances unless shadowed.
Since Dog does not define its own kingdom, it inherits the attribute from Animal.
If the subclass defines its own value, that shadows the parent's class attribute.
The parent still has its original value. The subclass simply defines its own attribute with the same name.
Instance Attributes Can Shadow Class Attributes
An instance can also shadow a class attribute by assigning the same name on the instance.
After u.role = "admin", the instance has its own role attribute, which shadows the class-level default.
This is one of the most important attribute rules in inheritance-heavy code.
Subclasses Do Not Automatically Reuse Parent __init__
A common misunderstanding is thinking that defining a subclass automatically runs the parent's initializer. If you override __init__, you usually need to call super().__init__(...) yourself.
Without super(), the inherited instance attributes may never be initialized.
Mutable Class Attributes Need Care
A classic trap is using a mutable class attribute when you meant per-instance state.
All instances share that same list. That is rarely the intended behavior.
The safer pattern is:
This is not just a Python detail; it is a direct consequence of how attribute lookup and inheritance work.
Common Pitfalls
The most common mistake is confusing class attributes with instance attributes.
Another mistake is overriding __init__ in a subclass and forgetting to call super().__init__, which leaves inherited instance state uninitialized.
Developers also get surprised when an instance assignment shadows a class attribute and changes only that one object.
Finally, mutable class attributes such as lists or dictionaries often produce accidental shared state across instances.
Summary
- Attribute lookup checks the instance first, then the class, then parent classes.
- Instance attributes are usually created per object in
__init__. - Class attributes are inherited and shared until overridden or shadowed.
- Subclasses often need
super().__init__to initialize inherited instance state. - Mutable class attributes are a common source of accidental shared behavior.

