Classes

INPUT · Slides

Inherit from another class

01 / 07

Two classes that are nearly the same

Say you have written a class for a member. It holds a name, and it can greet you.

Now you want to add a premium member. It holds a name and it greets exactly as a member does. The only difference is that postage is free.

Write a second class out in full for that and the same contents sit in two places. Fix one, forget the other, and now they disagree — that is the part that bites.

02 / 07

Put the original class in brackets

Write (Member) after the class name and you get a class that has taken on everything Member has. This is inheritance.

The PremiumMember below has neither __init__ nor greet written in it. Both work all the same. Anything you have not written is borrowed from the original class.

class Member:    def __init__(self, name):        self.name = name    def greet(self):        print(f"Hello, {self.name}")class PremiumMember(Member):    def perk(self):        print(f"{self.name} gets free postage")p = PremiumMember("Yui")p.greet()p.perk()

Result

Hello, Yui
Yui gets free postage

03 / 07

Parent and child

The one you started from is the parent (also called the base class); the one that took it on is the child (also called the derived class).

Inheriting runs one way only. The child can use what the parent has, but the parent knows nothing at all about the child. A real one made from the parent has no perk, so calling it is an error.

class Member:    def __init__(self, name):        self.name = nameclass PremiumMember(Member):    def perk(self):        print("free postage")m = Member("Haruto")m.perk()

Result

AttributeError: 'Member' object has no attribute 'perk'

04 / 07

Making one is inherited too

There is no __init__ in the child class, so why could you hand a name to PremiumMember("Yui")?

Because __init__ is inherited as well. What runs as a real one comes into being is the parent's __init__, so name is set up properly.

The __str__ from the last lesson works the same way. Write it on the parent and you can print a child instance as it is.

class Member:    def __init__(self, name, points):        self.name = name        self.points = points    def __str__(self):        return f"{self.name} ({self.points} points)"class PremiumMember(Member):    def perk(self):        print("free postage")p = PremiumMember("Yui", 120)print(p)p.perk()

Result

Yui (120 points)
free postage

05 / 07

One parent, as many children as you like

A single parent can have any number of children. The shared part lives in one place only, on the parent.

When the time comes to change it, there is one place to change. Inheritance is less about writing less and more about having fewer places to fix — hold on to that.

class Member:    def __init__(self, name):        self.name = name    def greet(self):        print(f"Hello, {self.name}")class PremiumMember(Member):    def perk(self):        print("free postage")class StudentMember(Member):    def discount(self):        print("half price for students")p = PremiumMember("Yui")s = StudentMember("Haruto")p.greet()s.greet()

Result

Hello, Yui
Hello, Haruto

06 / 07

What belongs on the parent

When you are unsure, ask "does it hold for every child?"

  • Holds for any member (the name, the greeting) → write it on the parent
  • Belongs to that one child (free postage, a student discount) → write it on the child

Move something up to the parent because two children happen to do the same thing, and the third child will make you regret it.

07 / 07

When you want the inherited behaviour changed

Everything so far has been "use what the parent has, as it is".

But you may well want the greeting for a premium member alone to be special. Rewriting inherited work in the child is the next lesson.

First, write out inheriting and using by hand.