I need help to use composition in Python - python

I hope you can help me out because I've been wrestling with this for two days now.
I want to make a program in Python to calculate all the nutrition requirement to build mussel.
I've got a dictionary where I stored the number of calories in 1 gr of protein, carbohydrates and Fat, I also have a dictionary containing the different requirements for the nutrition plan based on the gender
I would like to apply composition in my program, the final result I aim for is a composition class holding:
the current day
the information of the person
and the nutrition plan
I started off by creating a static class for the current day, then a class to print the personal information and finally the class to calculate the nutrition plan based on the information provided in the Personal class
Everything works just fine, I've got the result I wanted to, although when it comes to build my composition class I can't manage to do it, I will put the code I have and I hope you guys can help me with this.
Thank you very much.
import datetime
import pytz
calories = {'protein': 4, 'carbohydrates': 4, 'Fat': 9}
building = {
'man': {'Calories': 44, 'Protein': 2.2, 'carbohydrates': 5,
'Fat': 0},
'woman': {'Calories': 44, 'Protein': 2, 'carbohydrates': 5,
'Fat': 0}
}
class DateInfo:
#staticmethod
def current_time():
utc_time = datetime.datetime.utcnow()
print(pytz.utc.localize(utc_time).strftime(
"%m/%d/%Y-%H:%M:%S"))
class Person:
def __init__(self, name, age, weight, sex, goal):
self.name = name
self.age = age
self.weight = weight
self.sex = sex
self.goal = goal
def personal_info(self):
print('Name:{0.name}\nAge:{0.age}\nWeight:{0.weight}\nGoal:{0.goal}'.format(self))
class Building(Person):
def __init__(self, name, age, weight, sex, goal):
super().__init__(name, age, weight, sex, goal)
def nutrition_details(self):
factor = None
if self.sex == 'Man':
factor = building['man']
elif self.sex == 'Woman':
factor = building['woman']
total_calories = self.weight * factor['Calories']
gr_protein = self.weight * factor['Protein']
gr_carbohydrates = self.weight * factor['carbohydrates']
gr_fat = (total_calories - (gr_protein * calories['protein']
+ gr_carbohydrates * calories['carbohydrates'])) // calories['Fat']
print(f'Total calories: {total_calories}\n gr of protein'
f':{gr_protein}\n gr of carbohydrates:'
f'{gr_carbohydrates}\n gr of fat: {gr_fat}')
# Composition class where I want to store all the data
class NutritionPlan:
def __init__(self):
date_time = DateInfo()
self.person_info = Person()
self.nutrition_plan = Building()
def print_nutrition_details(self):
print(f'Date: {date_time}\nPerson Information: '
f'{self.person_info}\nNutrition Plan: '
f'{self.nutrition_plan}')
if __name__ == "__main__":
person_1 = Building('Guillermo', 30, 82, 'Man', 'Building')
DateInfo().current_time()
person_1.personal_info()
person_1.nutrition_details()
**Using composition**
02/02/2023-03:52:31
Name:Guillermo
Age:30
Weight:82
Goal:Building
Total calories: 3608
gr of protein:180.4
gr of carbohydrates:410
gr of fat: 138.0

Related

Make a method to go through the list of all objects and make a new list with specific objects

I need to make a method called filter in the main class Vehicles, with 2 arguments that go through the list all_vehicles, and add to the new_list, all the objects of that class that was passed by argument. And at the end make a print of the new list, new_list.
For example:
def filter(vehicles, name_of_vehicle):
new_list = []
print(f"From list {vehicles} found {name_of_vehicle}")
vehicles_listed = filter(all_vehicles, "Car")
And the print should look something like this.
"From the list all_vehicles were found [car1, car2, car3]".
class Vehicles:
color = ''
wheels = []
def __init__(self, color, wheels):
self.color = color
self.wheels = wheels
def filter(vehicles, name_of_vehicle):
new_list = []
print(f"From list {vehicles} found {name_of_vehicle}")
def __str__(self):
print(f"The bus is {self.color} and has {self.wheels} wheels.")
bus1 = Vehicles("white", 6)
bus1.__str__()
bus2 = Vehicles("blue", 6)
bus2.__str__()
class Car(Vehicles):
speed = 0
displacement = 0
def __init__(self, color, wheels, speed, displacement):
super().__init__(color, wheels)
self.color = color
self.wheels = wheels
self.speed = speed
self.displacement = displacement
def __str__(self):
print(f"The car is {self.color}, has {self.wheels} wheels, is traveling at {self.speed} mph and has {self.displacement} displacement.")
car1 = Car("black", 4, 70, 1000)
car1.__str__()
car2 = Car("grey", 4, 65, 950)
car2.__str__()
car3 = Car("green", 4, 90, 1100)
car3.__str__()
class Truck(Car):
cargo = 0
def __init__(self, color, wheels, speed, displacement, cargo):
super().__init__(color, wheels, speed, displacement)
self.color = color
self.wheels = wheels
self.speed = speed
self.displacement = displacement
self.cargo = cargo
def __str__(self):
print(f"The truck is {self.color}, has {self.wheels} wheels, is traveling at {self.speed} mph, has {self.displacement} displacement and is carrying {self.cargo} weight as cargo.")
truck1 = Truck("grey", 4, 40, 900, 1.525)
truck1.__str__()
truck2 = Truck("white", 4, 45, 920, 2.253)
truck2.__str__()
class Bike(Vehicles):
gears = ""
def __init__(self, color, wheels, gears):
super().__init__(color, wheels)
self.color = color
self.wheels = wheels
self.gears = gears
def __str__(self):
print(f"The bike is {self.color}, has {self.wheels} wheels and has {self.gears} changes.")
bike1 = Bike("orange", 2, 12)
bike1.__str__()
bike2 = Bike("black", 2, 10)
bike2.__str__()
class Motorbike(Bike):
speed = 0
displacement = 0
model = ""
def __init__(self, color, wheels, gears, speed, displacement, model):
super().__init__(color, wheels, gears)
self.color = color
self.wheels = wheels
self.gears = gears
self.speed = speed
self.displacement = displacement
self.model = model
def __str__(self):
print(f"The motorbike is {self.color}, has {self.wheels} wheels, has {self.gears} changes, is traveling at {self.speed} mph, has {self.displacement} displacement and is a {self.model} motorbike.")
motorbike1 = Motorbike("blue", 2, 5, 120, 600, "road")
motorbike1.__str__()
motorbike2 = Motorbike("black", 2, 7, 220, 1100, "race")
motorbike2.__str__()
all_vehicles = [bus1, bus2, car1, car2, car3, truck1, truck2, bike1, bike2, motorbike1, motorbike2]
def catalog(the_list, wheels):
num = 0
for vehicle in the_list:
if vehicle.wheels == wheels:
num += 1
print(f"Found {num} vehicles with {wheels} wheels.")
catalog(all_vehicles, 6)
First off, you should not name your method filter, since there is already a built-it function called filter in Python which you can see here. This could cause confusion for people that look at your code, and also cause what is called shadowing (see Wikipedia for more detail)
I suggest you name your method filter_vehicles instead.
Now, onto the code, we can use type().__name__ to get the string of an object. Here's a quick example via the Python interactive shell:
>>> class Car:
... def __init__(self, name):
... self.name = name
...
>>> class Motorcycle(Car):
... def __init__(self, name):
... super().__init__(name)
...
>>> a = Motorcycle("motor1")
>>> type(a).__name__
'Motorcycle'
Now back to your code, we can compare the type name to the provided vehicle name like so:
def filter_vehicles(vehicle_list, name):
new_vehicle_list = []
for v in vehicle_list:
#compare the typename to the name passed to the method
if type(v).__name__ == name:
new_vehicle_list.append(v.name)
return new_vehicle_list
Another, more concise way to do this is with list comprehension. You can learn more about it here:
def filter_vehicles(vehicle_list, name):
return [v.name for v in vehicle_list if type(v).__name__ == name]
Note that in order to properly print out the vehicle name. It is best to add a self.name attribute to the Vehicle class and its children and display that out, since you cannot display nor keep the variable names when it is changed to a list.
Another thing is that for my definition I returned the list instead of printing it out. If you really want to do that feel free, but do note that printing the result inside a method without returning anything is quite unconventional.

Is it possible to create nested class attributes?

I'm pretty new to Python and have recently learned about classes. I've been experimenting around with them and have come up with a student/course grading system. Here's the code so far:
class course:
TOTAL_COURSES = 0
def __init__(self, name, room, max_students):
self.name = name
self.room = room
self.max_students = max_students
self.student_list = []
course.TOTAL_COURSES += 1
def addStudent(self, student):
# Checks if the class is below max capacity
if len(self.student_list) < self.max_students:
self.student_list.append(student)
# Adds the course to the student's course list
student.course_list.append(self)
return True
return False
So this creates a course class, which I can add students to and set their rooms and other stuff. I've got another class, which is intended to store information on students:
class student:
TOTAL_STUDENTS = 0
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
# Courses in course_list are stored as objects
self.course_list = []
student.TOTAL_STUDENTS += 1
Pretty simple; I've just been stuck on how to create the actual grading system. If I were to do:
s1 = student("Tom", 17, "Male")
c1 = course("English", "E123", 25)
Would it be possible to then use "nested attributes"? So I'd assign that student's grade of a course to a value like:
s1.c1.grade = "A+"
This however doesn't work, and throws an (expected) AttributeError. So would I have to use my previously created course_list?
s1.course_list[0].grade = "A+"
Even then I'm not sure how I'd assign grade to that course object.
Here's a solution that addresses some of the above issues by assigning a "course slot" to a student, rather than the course itself. As you might imagine, there is a limit to the number of course slots available which depends on the course max size. The code can be developed a lot further, but I thought this could be good to get you started:
class Student:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
self.courses = {}
def addCourse(self, course):
if course.status=='Enrolled':
self.courses[course.name] = course
else:
self.courses[course.name] = course.status
class Course:
def __init__(self, name, room, max_students):
self.name = name
self.room = room
self.max_students = max_students
self.student_list = []
self.course_slots_filled = 0
self.course_slots_available = max_students
def __str__(self):
return 'Course_object_{}'.format(self.name)
def check_slots_available(self):
if self.course_slots_filled < self.max_students:
return True
else:
return False
class CourseSlot:
def __init__(self, name, student_name, status):
self.name = name
self.student_name = student_name
self.status = status
self.grade = 'No grade assigned'
def __repr__(self):
return 'CourseSlot_object_{}'.format(self.name)
def set_grade(self, grade):
self.grade = grade
def assign_course_slot(self, student_name):
if self.check_slots_available():
self.course_slots_filled+=1
self.course_slots_available-=1
status = 'Enrolled'
self.student_list.append(student_name)
else:
print('Sorry, {} class is full! {} not enrolled.'.format(self.name, student_name))
status = 'Not enrolled'
return self.CourseSlot(self.name, student_name, status)
Example usage
Instantiate courses:
physics = Course('Physics','101',5)
chemistry = Course('Chemistry','102',1)
Instantiate student 1 and assign a course slot:
s1 = Student("Tom", 17, "Male")
s1.addCourse(physics.assign_course_slot(s1.name))
s1.addCourse(chemistry.assign_course_slot(s1.name))
s1.courses['Physics'].set_grade('A+')
[v for v in s1.courses.values()]
# >>> [CourseSlot_object_Physics, CourseSlot_object_Chemistry]
Instantiate student 2 and assign a course slot
s2 = Student("Susan", 18, "Female")
s2.addCourse(physics.assign_course_slot(s2.name))
s2.addCourse(chemistry.assign_course_slot(s2.name))
#>>> Sorry, Chemistry class is full! Susan not enrolled.
Get course info:
print('Physics course slots filled: ',physics.course_slots_filled)
print('Physics course slots available: ',physics.course_slots_available)
print('Chemistry course slots filled: ',chemistry.course_slots_filled)
print('Chemistry course slots available: ',chemistry.course_slots_available)
#>>> Physics course slots filled: 2
# Physics course slots available: 3
# Chemistry course slots filled: 1
# Chemistry course slots available: 0
print('Physics student list: ',physics.student_list)
print('Chemistry student list: ',chemistry.student_list)
# >>> Physics student list: ['Tom', 'Susan']
# Chemistry student list: ['Tom']
for s in [s1,s2]:
for c in s.courses.values():
try:
print('{} {} grade: {}'.format(s.name, c.name, c.grade))
except AttributeError:
pass
# >>> Tom Physics grade: A+
# Tom Chemistry grade: No grade assigned
# Susan Physics grade: No grade assigned
I guess the cheat is that the course student_list only gets the name of the student and not the Student object, which could probably work if you pass it a unique ID and then iterate through a list of Student objects to match on ID. Something to think about anyway.
Grade is assigned to a combination of a student and a course object, so it cannot be a single attribute of any of them.
I would consider grades closer related to students than courses, so I would add a dictionary to student with a unique course ID (for example its name) as key and the grade as value. Next, you will probably need a function to select the course with the given ID (name) from your list of courses.
To further improve your code you can make course a hashable class, which is a class with a __hash__ method (look this up in the Python docs). Then you can use course objects directly as dictionary keys instead of working with IDs.

Unable to display data with __str__

This code is part of a larger program .. I am trying to generate a summary that displays the data taken from a user
class Mbilling:
def __init__(self, income, debit = 0, rent = 745):
self.income = income
self.debit = debit
self.rent = rent
class Display(Mbilling):
def listMbilling(self):
self.m = f"""
------------------------------------
--> Income = {self.income}
--> Debit = {self.debit}
--> Rent = {self.rent}
------------------------------------
"""
def __str__(self):
return self.m
and i am getting this error:
Traceback (most recent call last):
File "G:\Engineering\#ZicX\#Programming in Python\Basic Python\Tutorials\test.py", line 25, in <module>
receipt = Display()
TypeError: __init__() missing 1 required positional argument: 'income'
When i try these command:
d1 = Mbilling(5000, 0, 750)
receipt = Display()
print(receipt)
Need help to understand what's wrong ,, thanks !
I feel that the issue here is a matter of class inheritance. I am by no means a super() expert but here's what I can contribute:
Here is one example:
class MethodOne:
def __init__(self):
self.param_one = "Car"
self.param_two = 200
class MethodTwo(MethodOne):
def __init__(self):
super().__init__()
def __str__(self):
self.string_one = f"I have a {self.param_one}."
self.string_two = f"{self.param_two} minus 100 equals {self.param_two - 100}!"
return self.string_one + "\n" + self.string_two
And here is another example that more closely relates to what you are looking to achieve.
class Mbilling:
def __init__(self, income = 0, debit = 0, rent = 745):
self.income = income
self.debit = debit
self.rent = rent
print("Hi there. I am the parent")
class Display(Mbilling):
def __init__(self, income, debit, rent):
print("Hi, I am the child")
super().__init__()
def listMbilling(self):
self.m = f"""
------------------------------------
--> Income = {self.income}
--> Debit = {self.debit}
--> Rent = {self.rent}
------------------------------------
"""
def __str__(self):
self.listMbilling()
return self.m
d1 = Display(23, 40, 745)
print(d1)
Also, this link is super ;) useful https://www.educative.io/edpresso/what-is-super-in-python

Python. Using inheritance to write code to find price of car from dealership

I am trying to use inheritance to write a program which goal is to determine the price of a vehicle in a car lot as $4,000×number of wheels a vehicle has. You also buy vehicles. You offer a flat rate -10% of the miles driven on the vehicle. The flat rates are: for cars $7,500, for trucks: $9,000.
An example of the output should be:
>>> x=Car(4, 12000,'Mazda','CX5,2017,'Automatic','Red')
>>> y=Truck(7,8,15000,'Ford','Engine',1987)
>>> x.sale_price()
16000
>>> x.purchase_price()
6300.0
>>> x.getDescription()
'Mazda CX5 2017 -Red, 12000 miles >>> $16000'
>>> x.sell()
>>> x.sale_price()
0.0
>>> x.sell()
This item has been sold
>>> y.sale_price()
32000
>>> y.purchase_price()
7500.0
>>> y.getDescription()
'Ford Engine 1987, 15000 miles -7 seats >>> $32000'
>>> y.sell()
>>> y.sell()
This item has been sold
>>> y.sale_price()
0.0
I wrote the following code:
class Car:
def __init__(self, wheels, miles, make, model, year):
self.wheels = wheels
self.miles = miles
self.make = make
self.model = model
self.year = year
self.sold_on = False
def sell(self):
if self.sold_on == True:
print('This item has been sold')
else:
self.sold_on = True
def sale_price(self):
if self.sold_on:
return 0.0
return 4000 * self.wheels
def purchase_price(self):
return self.flat_rate - (0.10 * self.miles)
class Car(Car, object):
def __init__(self, wheels, miles, make, model, year, gear, color):
super(Car, self).__init__(wheels, miles, make, model, year)
self.gear = gear
self.color = color
self.flat_rate = 7500
def getDescription(self):
sale_price = self.sale_price()
return '{} {} {} - {}, {} miles >>> ${}'.format(self.make, self.model, self.year, self.color, self.miles, sale_price)
class Truck(Car, object):
def __init__(self, wheels, miles, make, model, year, seats):
super(Truck, self).__init__(wheels, miles, make, model, year)
self.seats = seats
self.flat_rate = 9000
def sale_price(self):
if self.sold_on:
return 0.0
return 4000
def getDescription(self):
sale_price = self.sale_price()
return '{} {} {}, {} miles - {} seats >>> ${}'.format(self.make, self.model, self.year, self.miles, self.seats, sale_price)
I am having an issue obtaining the desired output. I feel my logic is right. I am getting error messages saying "Duplicate bases for the class truck", "class Car already defined". I don't know how I can alter my code to eliminate these. Thank you for any help
class Vehicle(object):
# Things
class Car(Vehicle):
# other things
class Truck(Vehicle):
# yet more things

BMI in Python with file input

I have an assignment which I can't get through. I'm a beginner at programming and I want to understand it better for my course. Can someone help me? I really don't understand it.
This is the assignment:
The BMI is defined as weight/length2. A BMI between 18,5 and 25 as ideal and considers people with such a BMI healthy.
The program receives input consisting of two persons with their name, sex, length and weight.
Jack Johnson M 1.78 83
Maria Miller V 1.69 60
Process this input into structured data. To achieve this, use an useful class with useful methods to enhance the structure of the program. Use this structured data to print for each person: an appropriate style of address, surname, the BMI and a statement whether this is considered healthy or not.
Example:
Mr. Johnson’s BMI is 26.2 and is unhealthy.
Mrs. Miller’s BMI is 21.0 and is healthy.
This is what I have:
class Person(object):
def __init__(self):
self.first_name = first_name
self.last_name = last_name
self.sex = sex
self.length = length #m
self.weight = weight #kg
def bmi(self):
return self.weight / self.length ** 2
def healthy(self):
if BODYMASSINDEX <25 and BODYMASSINDEX>18.5:
person = healthy
else:
person = unhealthy
return person
from person import Person
file = open("BMIInput.txt")
invoer = file.read().splitlines()
details_person1 = invoer[0].split()
details_person2 = invoer[1].split()
person1 = Person(details_person1)
person2 = Person(details_person2)
print "%s's BMI is %.1f and is %s" %(person1.name, person1.bmi, person1.healthy)
The BMI Input is:
Jack Johnson M 1.78 83
Maria Miller V 1.69 60
Add the arguments to the init
class Person(object):
def __init__(self, first_name, last_name, sex, length, weight):
self.first_name = first_name
self.last_name = last_name
self.sex = sex
self.length = length #m
self.weight = weight #kg
def bmi(self):
return self.weight / self.length ** 2
def healthy(self):
if BODYMASSINDEX <25 and BODYMASSINDEX>18.5:
person = healthy
else:
person = unhealthy
return person
Then unpack the list:
from person import Person
file = open("BMIInput.txt")
invoer = file.read().splitlines()
details_person1 = invoer[0].split()
details_person2 = invoer[1].split()
person1 = Person(*details_person1)
person2 = Person(*details_person2)
print "%s's BMI is %.1f and is %s" %(person1.name, person1.bmi, person1.healthy)
Comment question about int, float is more what you need:
Just to solve the issue this is not clean nor the right way but it will work:
Inside the init
self.length = float(length) if type(length) != float else length
self.weight = float(weight) if type(weight) != float else weight
What I'd do is :
details_person1 = invoer[0].split()
details_person1[3] = float(details_person1[3])
details_person1[4] = float(details_person1[4])
The same thing with details_person2

Categories

Resources