BMI in Python with file input - python

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

Related

create a list from class user input

Create an employee class with the following members: name, age, id, salary
setData() - should allow employee data to be set via user input
getData()- should output employee data to the console
create a list of 5 employees. You can create a list of objects in the following way, appending the objects to the lists.
emp_object = []
for i in range(5):
emp_ object.append(ClassName())
I'm trying to do this exercise and this is what I got:
class employee:
def __init__(self, n = None, a = None, i = None, s = None):
self.name = n
self.age = a
self.id = i
self.salary = s
def setData(self):
self.n = input("Enter name: ")
self.a = int(input("Enter age: "))
self.i = int(input("Enter id: "))
self.s = int(input("Enter salary: "))
self.getData()
def getData(self):
print("Name:", self.name, self.age, self.id, self.salary)
e1 = employee()
e1.setData()
e2 = employee()
e2.setData()
e3 = employee()
e3.setData()
e4 = employee()
e4.setData()
e5 = employee()
e5.setData()
emp_object = []
for i in range(5):
emp_object.append(employee())
print(emp_object)
It prints the employee details as "None" and I need help to create a list
Expected Output:
Name id Age Salary
AAA 20 1 2000
BBB 22 2 2500
CCC 20 3 1500
DDD 22 4 3500
EEE 22 5 4000
Change the instance variable self.n ( in the setData method) to self.name to match the declaration your class init method ...and do the same for the self.a, self.i... variables .
I beleive the problem is that you are not setting the parameters to the ones you want in the setData function.
You need to do this:
class employee:
def __init__(self, n = None, a = None, i = None, s = None):
self.name = n
self.age = a
self.id = i
self.salary = s
def setData(self):
self.name = input("Enter name: ")
self.age = int(input("Enter age: "))
self.id = int(input("Enter id: "))
self.salary = int(input("Enter salary: "))
self.getData()
def getData(self):
print("Name:", self.name, self.age, self.id, self.salary)
The __init__ and setData are two separate functions.
First you want to separate some responsabilities for a better reading.
We will divide the problem in two parts :
Employee model
Input/output problem
Employee
Create a class who contains only employee data (we can use dataclasses but, I assume you're a beginner, so I'll keep simple)
class Employee:
def __init__(self, uid=None, name=None, age=None, salary=None):
self.name = name
self.age = age
self.id = uid
self.salary = salary
Output and Input
To display the employee's data in console, we can use __str__ function. It is used when you class need to be converted into a str (in print for isntance).
We then add an other method in charge to set employee's data.
Our Employee class become :
class Employee:
def __init__(self, uid=None, name=None, age=None, salary=None):
self.name = name
self.age = age
self.id = uid
self.salary = salary
def __str__(self):
return f"Name: {self.name}, {self.age}, {self.id}, {self.salary}"
def set_data(self):
self.name = input("Enter name: ")
self.age = int(input("Enter age: "))
self.id = int(input("Enter id: "))
self.salary = int(input("Enter salary: "))
Our class is complete. Now we will write the algorithm in charge to create 5 employees.
So under the Employee class :
if __name__ == '__main__':
# Empty list containing our employees
employees = []
# We loop 5 times.
for i in range(5):
# We create an employee
employee = Employee()
# We set the data
employee.set_data()
# We append our brand-new employee into the list
employees.append(employee)
# Now we display our data :
for employee in employees:
# We just need to print the object thanks to __str__ method
print(employee)
Tell me if I answered correctly to your problem !

How can I print each item in an unknown length list that is a class attribute as a string in python?

I have a class (Student) with different attributes, such as studentId, address, and courses. My str method for the class returns all the information that the user put in. However, for the attributes that are lists, such as courses, the location of the information is printed out instead of the actual information. Here is the code (sorry it's a little long, there's a bunch of classes):
class Person:
__name = None
__age = None
__address = None
def __init__(self, name, age=0, address=None):
self.set_name(name)
self.set_age(age)
self.set_address(address)
def __str__(self):
return 'Name: ' + self.__name + '\n' + \
'Age: ' + str(self.__age) + '\n' + \
'Address: ' + str(self.__address)
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_age(self, age):
self.__age = age
def get_age(self):
return self.__age
def set_address(self, address):
self.__address = address
def get_address(self):
return self.__address
class Student(Person):
def __init__(self, name, studentID= None, age= 0, address= None):
super(Student, self).__init__(name, age, address)
self.set_studentID(studentID)
self.__courses =[]
def __str__(self):
result = Person.__str__(self)
result += '\nStudent ID:' + self.get_studentID()
for item in self.__courses:
result += '\n ' + str(item)
return result
def set_studentID(self, studentID):
if isinstance(studentID, str) and len(studentID.strip()) > 0:
self.__studentID = studentID.strip()
else:
self.__studentID = 'NA'
def get_studentID(self):
return self.__studentID
def add_course(self, course):
print('in add_course')
self.__courses.append(course)
def get_courses(self):
for i in range(len(self.__courses)):
return self.__courses[i]
class Course:
__courseName = None
__dept = None
__credits = None
def __init__(self, courseName, dept= 'GE', credits= None):
self.set_courseName(courseName)
self.set_dept(dept)
self.set_credits(credits)
def __str__(self):
return self.get_courseName() + '/' + self.get_dept() + '/' + str(self.get_credits())
def set_courseName(self, courseName):
if isinstance(courseName, str) and len(courseName.strip()) > 0:
self.__courseName = courseName.strip()
else:
print('ERROR: Name must be a non-empty string')
raise TypeError('Name must be a non-empty string')
def get_courseName(self):
return self.__courseName
def set_dept(self, dept):
if isinstance(dept, str) and len(dept.strip()) > 0:
self.__dept = dept.strip()
else:
self.__dept = "GE"
def get_dept(self):
return self.__dept
def set_credits(self, credits):
if isinstance(credits, int) and credits > 0:
self.__credits = credits
else:
self.__credits = 3
def get_credits(self):
return self.__credits
students = []
def recordStudentEntry():
name = input('What is your name? ')
age = input('How old are you? ')
studentID= input('What is your student ID? ')
address = input('What is your address? ')
s1 = Student(name, studentID, int(age), address)
students.append(s1)
s1.add_course(recordCourseEntry())
print('\ndisplaying students...')
displayStudents()
print()
def recordCourseEntry():
courses = []
for i in range(2):
courseName = input('What is the name of one course you are taking? ')
dept = input('What department is your course in? ')
credits = input('How many credits is this course? ')
c1 = Course(courseName, dept, credits)
print(c1)
courses.append(c1)
displayCourses(courses)
return courses
def displayCourses(courses):
print('\ndisplaying courses of student... ')
for c in range(len(courses)):
print(courses[c])
def displayStudents():
for s in range(len(students)):
print()
print(students[s])
recordStudentEntry()
This is how the code above prints out the 'displaying students...' part:
displaying students...
Name: sam
Age: 33
Address: 123 st
Student ID:123abc
[<__main__.Course object at 0x000002BE36E0F7F0>, <__main__.Course object at
0x000002BE36E0F040>]
I know that it is printing out the location because I need to index into the list. However, the length of the list will be different every time. Normally if I wanted to index into a list, for example, to print a list of names, I would do:
listOfNames = ['sam', 'john', 'sara']
for i in range(len(listOfNames)):
print(listOfNames[i])
or
listOfNames = ['sam', 'john', 'sara']
for i in listOfNames:
print(i)
(not sure what if any difference there is between the 2 ways since they both print out the same way:)
sam
john
sara
How can I write something like the indexing into a list technique shown here in my str method for my class so that it prints the information and not the location?
It would be good to keep to the standard conventions for Python, such as naming
private attributes for objects with single underscores, not double underscores.
The latter are reserved for Python "internal" attributes and methods.
Also, it is convention to use object attributes for objects with get/set methods,
not class attributes. This will make it easier to inspect your objects, while
still maintaining data hiding. Example:
class Course:
def __init__(self, courseName, dept= 'GE', credits= None):
self._courseName = None
self._dept = None
self._credits = None
self.set_courseName(courseName)
...
Your question about why the courses don't print out the way you expected
is rooted in a programming error with the way you programmed the recording
of courses. In recordCourseEntry(), you record two courses and put them
in a list. However, you pass that to your Student object using a method
intended for one course at a time. My suggested fix would be:
...
# s1.add_course(recordCourseEntry())
courses = recordCourseEntry()
for course in courses:
s1.add_course(course)
...
This will probably be enough to get you going. An example output I got was:
Name: Virtual Scooter
Age: 33
Address: 101 University St.
Student ID:2021
ff/GE/3
gg/GE/3

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.

Print output is correct but analysis says its wrong

Using the pre-loaded class Person
Using the Person class, write a function print_friend_info(person) which accepts a single argument, of type Person, and:
prints out their name
prints out their age
if the person has any friends, prints 'Friends with {name}'
Write a function create_fry() which returns a Person instance representing Fry. Fry is 25 and his full name is 'Philip J. Fry'
Write a function make_friends(person_one, person_two) which sets each argument as the friend of the other.
I have gotten the right output with what needs to be printed but when I try run the code through our code Analyzer it says this error:
"You need to print the name of the person's friend in print_friend_info"
class Person(object):
def __init__(self, name, age, gender):
"""Construct a person object given their name, age and gender
Parameters:
name(str): The name of the person
age(int): The age of the person
gender(str): Either 'M' or 'F' for male or female
"""
self._name = name
self._age = age
self._gender = gender
self._friend = None
def __eq__(self, person):
return str(self) == str(person)
def __str__(self):
if self._gender == 'M':
title = 'Mr'
elif self._gender == 'F':
title = 'Miss'
else:
title = 'Ms'
return title + ' ' + self._name + ' ' + str(self._age)
def __repr__(self):
return 'Person: ' + str(self)
def get_name(self):
"""
(str) Return the name
"""
return self._name
def get_age(self):
"""
(int) Return the age
"""
return self._age
def get_gender(self):
"""
(str) Return the gender
"""
return self._gender
def set_friend(self, friend):
self._friend = friend
def get_friend(self):
"""
(Person) Return the friend
"""
return self._friend
def print_friend_info(person):
person_name = person.get_name()
person_age = person.get_age()
person_gender = person.get_gender()
person_friend = person.get_friend()
print (person_name)
print (person_age)
if person_friend == None:
return
else:
friendd = person_friend
nameoffriend = friendd.get_name()
print ('Friends with', nameoffriend)
return
def create_fry():
fry = Person("Philip J. Fry", 25, "M")
return fry
def make_friends(person_one, person_two):
made_friend1 = person_one.set_friend(person_two)
made_friend2 = person_two.set_friend(person_one)
return
--------- Test 1 ---------
Expected Output: Code Analyser
Test Result:
----- Analysis Errors -----
You need to print the name of the person's friend in print_friend_info
Input: bob = Person('Bob Smith', 40, 'M')
--------- Test 2 ---------
Expected Output: print_friend_info(bob)
Code Output: Bob Smith 40
Test Result: Correct!
Input: ed = Person('Ed', 8, 'M')
--------- Test 3 ---------
Expected Output: bob.set_friend(ed)
Code Output: Bob Smith 40 Friends with Ed
Test Result: Correct!
Input: fry = create_fry()
--------- Test 4 ---------
Expected Output: str(fry) -> 'Mr Philip J. Fry 25'
Test Result: Correct!
Input: leela = Person('T. Leela', 22, 'F')
--------- Test 5 ---------
Expected Output: make_friends(fry, leela)
Test Result: Correct!

Unable to Execute Python Methods

Despite my best attempt, I am unable to make a dent into getting the required output. I have provided my progress so far (after the question).
Write a class named Patient that has the following data attributes:
name ( type string), height (type float), has_hair (type
Boolean)
The Patient class should have an __init__ method (i.e., an initializer) that accepts the Patient’s name, height, and has_hair as arguments. These values should be assigned to the object's name, height, and has_hair data attributes. By default, let has_hair = 0
Each Patient should start with 0 tablets, stored in an attribute tablets.
A collect_tablets(number) method adds the given number of tablets to the Patient's number. This function should also be able to be called as collect_tablets() which just adds one barange to the total number.
An eat() method consumes one tablet from the Patient's total, but increases the height of the Patient by 0.1m. If the Patient does not have any baranges, the method should print
"I don't have any tablets to eat!."
A 'feast()' method consumes five tablets from the Patient's total. If the Patient is not hairy when he feasts, he grows hair. If the Patient is already hairy when he feasts, he grows by 50% instead (for example: a 2 m Patient grows to 3 m).
A bald Patient that feasts, only grows hair, he does not grow in height unless he feasts later. If the Patient does not have enough tablets for a feast, the method should print
“I don't have enough tablets to feast!.”
TEST CASE:
hungry_patient = Patient("Jack", 1.89)
hungry_patient.collect_tablets()
hungry_patient.eat()
print(hungry_patient)
OUTPUT
Jack is a 1.99 m tall blork!
My Code is :
class Patient:
def __init__(self, name, height, tablets = 0, has_hair=False):
"""Blork constructor"""
self.name = name
self.height = height
self.tablets = tablets
self.has_hair = has_hair
def collect_tablets(self):
self.tablets = self.tablets + 1
def eat(self):
if self.tablets == 0:
print(“I don't have enough to eat”)
else:
self.tablets = self.tablets - 1
self.height = self.height + 0.1
def feast(self):
if self.tablets >= 5:
if self.has_hair == True:
self.height = self.height + 0.5 * (self.height)
if self.has_hair == False:
self.has_hair = True
else:
print("I don't have enough baranges to feast!")
hungry_patient = Patient("Jack", 1.89)
hungry_patient.collect_tablets()
hungry_patient.eat()
print(hungry_patient)
I am not able to get the program to execute.
Please help and advise me as to what I am doing wrong.
First, there are invalid characters in your code. On line 14:
print(“I don't have enough to eat”)
change the special opening and closing quotes to standard double quotes:
print("I don't have enough to eat")
After fixing the above and some indentation issues, the code runs, but the output is just a raw string representation of the object instance you're printing.
<__main__.Patient instance at 0x7f17180af3b0>
In order to define a custom string representation, you need to define an __str__ and/or __repr__ method on your class. Have a look at the Python documentation
def __str__(self):
return "%s is a %s m tall blork!" % (self.name, self.height)
Full working code:
class Patient:
def __init__(self, name, height, tablets = 0, has_hair=False):
"""Blork constructor"""
self.name = name
self.height = height
self.tablets = tablets
self.has_hair = has_hair
def collect_tablets(self):
self.tablets = self.tablets + 1
def eat(self):
if self.tablets == 0:
print("I don't have enough to eat")
else:
self.tablets = self.tablets - 1
self.height = self.height + 0.1
def feast(self):
if self.tablets >= 5:
if self.has_hair == True:
self.height = self.height + 0.5 * (self.height)
if self.has_hair == False:
self.has_hair = True
else:
print("I don't have enough baranges to feast!")
def __str__(self):
return "%s is a %s m tall blork!" % (self.name, self.height)
hungry_patient = Patient("Jack", 1.89)
hungry_patient.collect_tablets()
hungry_patient.eat()
print(hungry_patient)

Categories

Resources