Object-oriented model for a calorie counter sporting polymorphic methods for both genders.
Concerns:
- BPM curve for exercise acts of longer duration: can this be added without being too invasive?
- Side-effect or coupling between
main
and theread_person_attributes
function through thedel
statement which modifies the argument: is this a necessary evil, or can it be removed?
from abc import ABC, abstractmethod def main(): person_attributes = read_person_attributes() person = PersonFactory.make_person(person_attributes) print("You've burned approximately {0} calories.".format(round(person.calories_burned, 1))) def read_person_attributes(): """Prompts a user for their details """ person_attributes = { 'gender': input('Your gender (male, female): '), 'weight_kg': int(input('Your weight in kg: ')), 'age': int(input('Your age: ')), 'bpm': int(input('Your heart rate in bpm: ')), 'exercise_duration_min': int(input('Your exercise duration in minutes: ')) } return person_attributes class Person(ABC): def __init__(self, weight_kg, bpm, age, exercise_duration_min): self.weight_kg = weight_kg self.age = age self.bpm = bpm self.exercise_duration_min = exercise_duration_min @property @abstractmethod def calories_burned(self): raise NotImplementedError class Male(Person): @property def calories_burned(self): return ((self.age * 0.2017) - (self.weight_kg * 0.09036) + (self.bpm * 0.6309) - 55.0969) * self.exercise_duration_min / 4.184 class Female(Person): @property def calories_burned(self): return ((self.age * 0.074) - (self.weight_kg * 0.05741) + (self.bpm * 0.4472) - 20.4022) * self.exercise_duration_min / 4.184 class PersonFactory: @staticmethod def make_person(person_attributes): """ Instantiate a person of the proper gender based on the provided attributes. Args: person_attributes: A dictionary containing the keys: ('gender', 'age, 'weight_kg', exercise_duration_min, bpm) """ gender = person_attributes['gender'].lower() del person_attributes['gender'] if gender == 'male': return Male(**person_attributes) elif gender == 'female': return Female(**person_attributes) else: raise RuntimeError('Invalid gender') if __name__ == '__main__': main()