Inheritance Part 2: super()

Lesson 4 of 7 • 10 XP

Keep your place in this quest

Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.

When a class inherits from a parent class, the child class can have its own instance variables and methods, but sometimes it still needs to use parts of the parent’s code.

This is where the super() function comes in.
It lets the child class access methods (and indirectly attributes) from its parent class — without having to hardcode the parent’s name.

One of the most common uses of super() is to call the parent’s constructor (__init__) from inside the child class, so the parent can set up its own attributes before the child adds any new ones.

When you create a child class that defines its own init method, it overrides the parent’s init. This means that when you create an object from the child class, only the child’s init will run — the parent’s constructor won’t be called automatically. As a result, any setup logic, default values, or attributes defined in the parent’s init will be skipped entirely, leaving them undefined in the child object. This can cause unexpected errors if your parent class was responsible for important initialization work. To avoid losing that behavior, you should call super().init() inside the child’s constructor, which explicitly runs the parent’s initialization before adding or overriding anything in the child.

Let's explore that now!


Why Use super().__init__()?

When you create a subclass, you might give it extra data to store.
However, you still want the parent’s attributes to be initialized properly. Instead of rewriting the parent’s initialization code, you simply call it using super().__init__().

Example: Adding a New Attribute in a Subclass

Let’s say we have an Animal class that stores name and age.
We want to make a Dog subclass that also stores the dog’s breed (its type), but we still want to use Animal’s constructor to set name and age.

class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

class Dog(Animal):
    def __init__(self, name, age, breed):
        super().__init__(name, age)  # Call Animal's constructor
        self.breed = breed           # Add Dog's own attribute
````

---

## How This Works Step-by-Step

1. When we create a `Dog` object, Python runs the `Dog` class’s `__init__` method.
2. Inside `Dog.__init__`, the line `super().__init__(name, age)` calls `Animal.__init__`.
3. The parent constructor (`Animal.__init__`) sets `self.name` and `self.age`.
4. Control returns to `Dog.__init__`, which then sets `self.breed`.

This way:

* The parent’s attributes are initialized exactly as the parent intended.
* The child class can add its own attributes without duplicating code.

## Using the Class

```python
dog = Dog("Rex", 4, "Golden Retriever")

print(dog.name)   # Rex
print(dog.age)    # 4
print(dog.breed)  # Golden Retriever

Why super() Is Better Than Calling the Parent by Name

You could call Animal.__init__(self, name, age) directly, but using super() is more flexible:

  • It automatically handles multiple inheritance (if your class inherits from more than one parent).
  • It makes your code easier to maintain — if you ever rename the parent class, you don’t have to change every reference.
  • It clearly communicates that you are intentionally calling a method from the parent class.
TIP: Always call `super().__init__()` before setting the child’s own attributes, so all parent attributes are ready to use.

Wrapping Up

super() is your link to the parent class. Use it when you want to:

  • Reuse parent setup code.
  • Extend parent functionality without duplicating it.
  • Keep your code clean, maintainable, and ready for changes in the class hierarchy.

In the next lesson, we’ll explore private methods and variables — a way to protect your class’s internal data from being accessed or changed from the outside.