Classes working together
To finish this part, here is a larger program where several classes work together: a small city bike system. Read it slowly, class by class. Everything in it is something you've already learned; the point is how the pieces fit.
- A
Bikehas a number. A class variable hands out the numbers, and the model has a default value. - A
Stationhas a fixed number of slots and a private list of theBikeobjects docked there.releasereturns a bike, orNonewhen the station is empty. - A
Riderhas at most one bike at a time: the attributebikeisNonewhile they walk.
class Bike:
next_number = 1
def __init__(self, model="city"):
self.number = Bike.next_number
Bike.next_number += 1
self.model = model
def __str__(self):
return f"bike {self.number} ({self.model})"
class Station:
def __init__(self, name, slots):
self.__name = name
self.__slots = slots
self.__bikes = []
@property
def name(self):
return self.__name
def free_slots(self):
return self.__slots - len(self.__bikes)
def dock(self, bike):
if self.free_slots() == 0:
return False
self.__bikes.append(bike)
return True
def release(self):
if len(self.__bikes) == 0:
return None
return self.__bikes.pop(0)
def __str__(self):
return f"{self.__name}: bikes {len(self.__bikes)}, free {self.free_slots()}"
class Rider:
def __init__(self, name):
self.name = name
self.bike = None
def rent_from(self, station):
if self.bike is not None:
return
self.bike = station.release()
if self.bike is None:
print(f"{self.name}: no bikes at {station.name}")
else:
print(f"{self.name} took {self.bike} at {station.name}")
def return_to(self, station):
if self.bike is not None and station.dock(self.bike):
print(f"{self.name} left {self.bike} at {station.name}")
self.bike = None
park = Station("Park", 2)
harbor = Station("Harbor", 1)
park.dock(Bike())
park.dock(Bike("cargo"))
print(park.dock(Bike()))
ada = Rider("Ada")
ben = Rider("Ben")
ada.rent_from(park)
ada.return_to(harbor)
ben.rent_from(harbor)
ada.rent_from(harbor)
print(park)
print(harbor)
False
Ada took bike 1 (city) at Park
Ada left bike 1 (city) at Harbor
Ben took bike 1 (city) at Harbor
Ada: no bikes at Harbor
Park: bikes 1, free 1
Harbor: bikes 0, free 1Some things to notice:
- Each class looks after its own data. The rider never touches the station's list; it asks the station with
station.release()andstation.dock(...). So the station alone decides whether there's room, and its list can stay private. - One object, many places. Bike 1 is created once. It moves from the park's list to Ada, to the harbor's list, to Ben, but it's always the same object; only references to it move around.
Nonemeans "nothing here".releasereturnsNonefrom an empty station, andrent_fromchecks for it before printing. The third bike made, number 3, never found room, so it exists in no list at all.- Methods take objects as arguments.
rent_from(station)works with any station, which is why oneRiderclass serves the whole city.