Why does printing a run, a swim and a plain workout all run the same page-long `__str__` that appears in none of their state dictionaries?
Short drills on what this video just taught. Write the code, run the checks, and reveal the answer only if you are stuck.
The classes above are already defined; do not create any instances. Assign to in_own_dict whether the name '__str__' is one of the names RunWorkout defines for itself in its own state dictionary, and assign to drawer the __str__ a RunWorkout actually uses when one of them is printed. Assign both answers to in_own_dict and drawer.
from datetime import datetime
# The lecture's fitness tracker, trimmed. The emoji icons are written here as
# two-character ASCII stand-ins so the cards line up in this editor.
class Workout(object):
cal_per_hr = 200
def __init__(self, start, end, calories=None):
self.start = datetime.strptime(start, '%m/%d/%Y %I:%M %p')
self.end = datetime.strptime(end, '%m/%d/%Y %I:%M %p')
self.icon = '##'
self.kind = 'Workout'
self.calories = calories
def get_duration(self):
return self.end - self.start
def get_kind(self):
return self.kind
def get_calories(self):
if self.calories is None:
return self.cal_per_hr * self.get_duration().total_seconds() / 3600
return self.calories
def __str__(self):
width = 16
retstr = f"|{'-'*width}|\n"
retstr += f"|{' '*width}|\n"
retstr += f"| {self.icon}{' '*(width-3)}|\n"
retstr += f"| {self.kind}{' '*(width-len(self.kind)-1)}|\n"
retstr += f"|{' '*width}|\n"
duration_str = str(self.get_duration())
retstr += f"| {duration_str}{' '*(width-len(duration_str)-1)}|\n"
cal_str = f"{round(self.get_calories(), 1)}"
retstr += f"| {cal_str} Calories {' '*(width-len(cal_str)-11)}|\n"
retstr += f"|{' '*width}|\n"
retstr += f"|{'_'*width}|\n"
return retstr
class RunWorkout(Workout):
cals_per_km = 100
def __init__(self, start, end, elev=0, calories=None, route_gps_points=None):
super().__init__(start, end, calories)
self.icon = '>>'
self.kind = 'Running'
self.elev = elev
self.route_gps_points = route_gps_points
def get_elev(self):
return self.elev
def set_elev(self, elev):
self.elev = elev
def get_calories(self):
if self.calories is None:
return super().get_calories()
return self.calories
def __eq__(self, other):
return self.start == other.start and self.end == other.end
class SwimWorkout(Workout):
"""A swim workout."""
cal_per_hr = 400
def __init__(self, start, end, pace=0):
super().__init__(start, end)
self.icon = '~~'
self.kind = 'Swimming'
self.pace = pace
def get_pace(self):
return self.pace
def get_calories(self):
return self.cal_per_hr * self.get_duration().total_seconds() / 3600The subclass dictionary and what it does not copy
List the keys RunWorkout.__dict__ shows, cals_per_km, __init__, get_elev, set_elev, get_calories and __eq__, note the parent's getters and setters are absent, and give the instance's seven data attributes.
__str__ returning a card sixteen characters wide
State that __str__ returns a string rather than printing one, and write how retstr is concatenated line by line from self.icon, self.kind, get_duration() and get_calories().
Printing a workout, a run and a swim
Note that neither RunWorkout nor SwimWorkout defines a __str__, print one object of each type, and record that only the icon and the label differ between the three cards.