Python Arena
Step 1 of 4

Inheriting from a base class

Some classes turn out to be almost the same. Say you're writing a small adventure game with wizards and knights. Both have a name and health points, both can take damage, and both print the same way. Only one thing differs: a wizard casts spells and a knight raises a shield. Written as two separate classes, much of the code is there twice:

class Wizard:
    def __init__(self, name, health):
        self.name = name
        self.health = health

    def take_damage(self, amount):
        self.health -= amount

    def cast_spell(self):
        return f"{self.name} casts a fireball!"


class Knight:
    def __init__(self, name, health):
        self.name = name
        self.health = health

    def take_damage(self, amount):
        self.health -= amount

    def raise_shield(self):
        return f"{self.name} raises a shield."

Code that is written twice has to be fixed twice, and sooner or later one copy gets fixed and the other doesn't. Merging the two into one class with every method isn't a good answer either: then every knight could cast spells.

A base class and derived classes

Inheritance solves this. You write what the classes share once, in a base class, and each special class inherits everything from it and adds only what is its own. To make a class inherit another, write the base class's name in parentheses after the new class's name:

class Character:
    def __init__(self, name, health):
        self.name = name
        self.health = health

    def take_damage(self, amount):
        self.health -= amount

    def __str__(self):
        return f"{self.name} ({self.health} health)"


class Wizard(Character):
    def cast_spell(self):
        return f"{self.name} casts a fireball!"


class Knight(Character):
    def raise_shield(self):
        return f"{self.name} raises a shield."


elva = Wizard("Elva", 30)
bram = Knight("Bram", 50)
bram.take_damage(12)
print(elva)
print(bram)
print(elva.cast_spell())
print(bram.raise_shield())
Output
Elva (30 health)
Bram (38 health)
Elva casts a fireball!
Bram raises a shield.

Wizard and Knight are derived classes of Character. (You'll also hear subclass or child class for a derived class, and superclass or parent class for the base class.) Neither has a constructor of its own, so Wizard("Elva", 30) runs the constructor it inherits from Character. take_damage and __str__ are written once, but they work for both. And cast_spell can use self.name, because every wizard got its name from that same constructor.

Inheritance goes one way

A derived class gets everything its base class has, but not the other way around. A plain Character has no cast_spell:

class Character:
    def __init__(self, name):
        self.name = name


class Wizard(Character):
    def cast_spell(self):
        return f"{self.name} casts a fireball!"


elva = Wizard("Elva")
print(elva.cast_spell())
pip = Character("Pip")
print(pip.cast_spell())
Output
Elva casts a fireball!
Python stops with
Traceback (most recent call last):
  File "main.py", line 14, in <module>
    print(pip.cast_spell())
          ^^^^^^^^^^^^^^
AttributeError: 'Character' object has no attribute 'cast_spell'

Two derived classes don't share their own methods either: a knight can't cast spells. A quick test of a design is the words "is a". A wizard is a character, so Wizard(Character) makes sense. A character isn't always a wizard, so the spells belong in Wizard only.

Your task

Challenge 1 of 3

A truck is a vehicle that can carry a load. Fill in the blank so that Truck inherits Vehicle, and the program prints:

TRK-42, 6 wheels
TRK-42 carries 12 tons

Challenge 2

A healer is a character who can heal others. Write a class Healer that inherits Character, with one method of its own: heal(other) adds 10 to the health of the character other. Don't write a constructor or a __str__ for Healer: it inherits them. For example,

iris = Healer("Iris", 20)
tom = Character("Tom", 15)
iris.heal(tom)
iris.heal(tom)
print(tom)
print(iris)

should print:

Tom (35 health)
Iris (20 health)

Challenge 3

What does this program print? Type each line it prints.