Skip to content
BetaDE
Lesson 27 of 35Python

Python · Lesson 27 · 35 minutes

Bug detective 2: classes and exceptions

What you'll learn

  • Read longer error messages (tracebacks) step by step
  • Find bugs in classes (forgotten self, wrong calculation)
  • Check things deliberately with assert and f"{x=}"

Reading long error messages

The bigger a program, the longer the error messages get. Python then shows a traceback: the chain of function calls that led to the error. The most important part is still the last line:

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

    def introduce(self):
        return "I am " + self.nmae


dog = Animal("Rex")
print(dog.introduce())

AttributeError: 'Animal' object has no attribute 'nmae' – a typo in the attribute name. Codelix even suggests the right name.

The classic: forgetting self

class Counter:
    def __init__(self):
        count = 0          # ← without self. this is just a local variable

    def plus(self):
        self.count += 1


c = Counter()
c.plus()

In a method, everything the object should remember belongs on self. Otherwise it’s gone once the method ends.

Tool: assert and f”{x=}”

With assert you check an assumption. If it’s wrong, Python stops straight away – exactly where things first go wrong:

def net(gross):
    return gross / 1.2


price = net(120)
print(f"{price=}")          # shows the name AND the value
assert round(price) == 100, "Net price is wrong"
print("All correct!")

f"{price=}" is a debugging trick: Python writes the name along with the value.

Detective rule 2: explain your code out loud – to a friend, a cuddly toy or a rubber duck. While explaining, you’ll surprisingly often spot the bug yourself. Professionals call this rubber duck debugging.

Your task

Your turn

The class Account has three bugs. It should work like this: a new account starts with a balance of 0. deposit(amount) increases the balance – negative amounts should raise a ValueError. withdraw(amount) reduces the balance and raises a ValueError if there isn't enough money.

class Account:
    def __init__(self, owner):
        self.owner = owner
        balance = 0

    def deposit(self, amount):
        if amount < 0:
            print("Only positive amounts!")
        self.balance += amount

    def withdraw(self, amount):
        if amount > self.balance:
            raise ValueError("Not enough money")
        self.balance + amount


account = Account("Ana")
account.deposit(50)
account.withdraw(20)
print(account.owner, "has", account.balance, "pounds")

Solve it without hints to earn a ⭐ on your progress page.

Show solution

Try it yourself first – mistakes teach you the most. Here is one possible solution:

class Account:
    def __init__(self, owner):
        self.owner = owner
        self.balance = 0

    def deposit(self, amount):
        if amount < 0:
            raise ValueError("Only positive amounts!")
        self.balance += amount

    def withdraw(self, amount):
        if amount > self.balance:
            raise ValueError("Not enough money")
        self.balance -= amount


account = Account("Ana")
account.deposit(50)
account.withdraw(20)
print(account.owner, "has", account.balance, "pounds")