Lesson 28 of 35Python
Python · Lesson 28 · 60 minutes
Boss level: the library
What you'll learn
- Design your own class with several methods
- Report errors with your own exceptions
- Save data in a file and load it again
The intermediate boss
In the intermediate stage you learned to catch errors, write files, build your own classes and test code. Now it all comes together: a small management program, just like real libraries use.
Reminder: raising exceptions yourself
A good class reports errors loudly instead of quietly doing the wrong thing:
class Safe:
def __init__(self, code):
self.code = code
self.open = False
def unlock(self, attempt):
if attempt != self.code:
raise ValueError("Wrong code!")
self.open = True
s = Safe(1234)
try:
s.unlock(1111)
except ValueError as error:
print("Caught:", error)Reminder: writing files
with open("list.txt", "w") as file:
for name, age in [("Ana", 12), ("Ben", 13)]:
file.write(f"{name};{age}\n")
print(open("list.txt").read())Strategy for the boss
- Data first:
self.booksis a dictionary title →True/False. Everything else works with it. - Then method by method: test each one straight away with a few lines below the class.
- Error cases last: what happens with unknown books or books that are already lent out?
Keep building: a method
load(filename)that reads a saved file back in – then your library even survives the end of the program.
Your task
Your turn
Build the class Library. add(title) adds a book (available). lend(title) lends it out – unknown titles raise a KeyError, books that are already lent raise a ValueError. give_back(title) makes it available again. available() returns a sorted list of the available titles. save(filename) writes one line per book, Title;yes or Title;no (available or not).
class Library:
def __init__(self):
self.books = {} # title → True (available) or False (lent out)
def add(self, title):
pass
def lend(self, title):
pass
def give_back(self, title):
pass
def available(self):
pass
def save(self, filename):
pass
library = Library()
library.add("Momo")
library.add("Matilda")
library.lend("Momo")
print(library.available())- Something to think about
add sets
self.books[title]=True. available collects all titles withTrueand returnssorted(...). - Which command helps?
In lend, first check whether the title is in
self.booksat all (otherwise raiseKeyError(title)), then whether it's available (otherwise raiseValueError(...)).Open the file with
withopen(filename, "w")as file and writef"{title};yes"orf"{title};no"plus a line break for every book. - Gap code – fill in the ___
class Library: def __init__(self): self.books = {} # title → True (available) or False (lent out) def add(self, title): self.books[title] = ___ def lend(self, title): if ___: ___ if ___: ___ self.books[title] = ___ def give_back(self, title): self.books[title] = ___ def available(self): return ___ def save(self, filename): with ___ as file: for title, free in ___: file.write(___) library = Library() library.add("Momo") library.add("Matilda") library.lend("Momo") print(library.available())
Solve it without hints to earn a ⭐ on your progress page.
Show solution🔒 Unlocks after all hints or 2 checks
Try it yourself first – mistakes teach you the most. Here is one possible solution:
class Library:
def __init__(self):
self.books = {} # title → True (available) or False (lent out)
def add(self, title):
self.books[title] = True
def lend(self, title):
if title not in self.books:
raise KeyError(title)
if not self.books[title]:
raise ValueError(f"{title} is already lent out")
self.books[title] = False
def give_back(self, title):
self.books[title] = True
def available(self):
return sorted(title for title, free in self.books.items() if free)
def save(self, filename):
with open(filename, "w") as file:
for title, free in self.books.items():
file.write(f"{title};{'yes' if free else 'no'}\n")
library = Library()
library.add("Momo")
library.add("Matilda")
library.lend("Momo")
print(library.available())