A collection you can search
A larger program often has two kinds of classes: one for a single thing, and one for a collection of those things. Here a Hike knows its own data and how to show itself, and a Logbook keeps the hikes someone plans to walk and answers questions about them:
class Hike:
def __init__(self, name, km):
self.name = name
self.km = km
self.walked = False
def __str__(self):
status = "walked" if self.walked else "not yet"
return f"{self.name} ({self.km} km, {status})"
class Logbook:
def __init__(self):
self.hikes = []
def add(self, name, km):
self.hikes.append(Hike(name, km))
def mark_walked(self, name):
for hike in self.hikes:
if hike.name == name:
hike.walked = True
def find(self, word):
found = []
for hike in self.hikes:
if word.lower() in hike.name.lower():
found.append(hike)
return found
def km_left(self):
total = 0
for hike in self.hikes:
if not hike.walked:
total += hike.km
return total
summer = Logbook()
summer.add("Lake Path", 5)
summer.add("Ridge Loop", 12)
summer.add("Old lake trail", 9)
summer.mark_walked("Lake Path")
for hike in summer.find("lake"):
print(hike)
print("Km left:", summer.km_left())
Lake Path (5 km, walked)
Old lake trail (9 km, not yet)
Km left: 21A few things to notice:
- The client only calls
addwith a name and a length.Logbookmakes theHikeobjects itself and keeps them in its list. findis a search: it goes through the list and collects the hikes that match into a new list. It compares in small letters, solakealso findsLake.findreturns theHikeobjects themselves, so the client can print them (with their__str__) or use their attributes.mark_walkedchanges the attribute of a hike that is in the list. The list holds references to the hikes, so the change stays.
Searching for the best match
Another common search finds the one item that is best by some measure. Such a method goes through the list once and remembers the best item so far. If the list can be empty, it needs an answer for that too:
def longest(self):
if len(self.hikes) == 0:
return None
best = self.hikes[0]
for hike in self.hikes:
if hike.km > best.km:
best = hike
return best
The examples of this part have grown step by step into something like real programs: classes that keep their data valid, show themselves with __str__, and answer questions about what they hold.