Inheritance
Attributes
Object-Oriented Programming
OOP Concepts
Programming Basics

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:

  1. check the instance itself
  2. check the class
  3. check parent classes according to the method resolution order

A small example makes this concrete.

python
1class Animal:
2    species = "animal"
3
4    def __init__(self, name):
5        self.name = name
6
7
8class Dog(Animal):
9    pass
10
11
12d = Dog("Rex")
13print(d.name)
14print(d.species)

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__.

python
1class Vehicle:
2    def __init__(self, make, model):
3        self.make = make
4        self.model = model
5
6
7class Car(Vehicle):
8    def __init__(self, make, model, seats):
9        super().__init__(make, model)
10        self.seats = seats

Here the Car instance gets:

  • 'make and model from the parent initializer'
  • 'seats from 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.

python
1class Animal:
2    kingdom = "animalia"
3
4
5class Dog(Animal):
6    pass
7
8
9print(Dog.kingdom)

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.

python
1class Bird(Animal):
2    kingdom = "aves-example"
3
4print(Bird.kingdom)

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.

python
1class User:
2    role = "guest"
3
4
5u = User()
6print(u.role)
7
8u.role = "admin"
9print(u.role)
10print(User.role)

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.

python
1class Person:
2    def __init__(self, name):
3        self.name = name
4
5
6class Employee(Person):
7    def __init__(self, name, department):
8        super().__init__(name)
9        self.department = department

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.

python
class Team:
    members = []

All instances share that same list. That is rarely the intended behavior.

The safer pattern is:

python
class Team:
    def __init__(self):
        self.members = []

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.

Course illustration
Course illustration

All Rights Reserved.