1

Problem 1

First I need to create a Person class. Then I must write a status method in the Person class. The method should call the bmi() method and, based on the returned result, return the person's status as a string, using the following rules:

BMI               Status
< 18.5            Underweight
>= 18.5 and < 25  Normal
>= 25 and < 30    Overweight
>= 30             Obese

This I was able to do. And now, I am to do the following:

Problem 2

Add after the class a function read_people(csv_filename) that takes as a parameter the name of a CSV file of person data and returns a list of Person objects, one for each line in the input file (and in the same order). The function should only require 7 - 10 lines, excluding comments and blank lines. The maximum function length is set to 10 statements for this question.

The input CSV file will contain 4 columns:

a name (not containing a comma)
an integer age (in years)
a float weight (in kg)
a float height (in metres)

For example, the file people1.csv used in the example below contains the following:

Rolly Polly,47,148.8,1.67
Rosie Donell,23,89.4,1.82
Rambo Stallone,19,59,2.0
Sharon Stone,14,50,1.6
Arnold Shwarnegger,70,59.2,1.65

Test Case

persons = read_people("people1.csv")
for person in persons:
    print(person)

Expected Result

Roly Polly (47) has a bmi of 53.35. Their status is Obese.
Rosie Donell (23) has a bmi of 26.99. Their status is Overweight.
Rambo Stallone (19) has a bmi of 14.75. Their status is Underweight.
Sharon Stone (14) has a bmi of 19.53. Their status is Normal.
Arnold Shwarnegger (70) has a bmi of 21.74. Their status is Normal.

I tried the following code (and FAILED)

"""File for creating Person objects"""

class Person:
    """Defines a Person class, suitable for use in a hospital context.
        Methods: bmi()
    """

    def __init__(self, name, age, weight, height):
        """Creates a new Person object with the specified name, age, weight
           and height"""
        self.name = name
        self.age = age
        self.weight = weight
        self.height = height

    def bmi(self):
        """Returns the body mass index of the person"""
        return self.weight / (self.height * self.height)

    def status(self):
        """dsjhf dsfkj"""
        status = ""
        bmi = Person.bmi(self)
        if bmi < 18.5:
            status = "Underweight"
        if bmi >= 18.5 and bmi < 25:
            status = "Normal"
        if bmi >= 25 and bmi < 30:
            status = "Overweight"
        if bmi >= 30:
            status = "Obese"
        return status

    def __str__(self):
        """outputs data"""
        ans1 = Person.bmi(self)
        ans2 = Person.status(self)
        answer = "{0} ({1}) has a bmi of {2:.02f}. Their status is {3}."
        return answer.format(self.name, self.age, ans1, ans2)

    def read_people(csv_filename):
        """reads file and sorts it then runs through a class"""
        lst = []
        final = []
        file = open(csv_filename, 'r')

        for row in file:
            lst.append(row)
        return lst

    persons = read_people("people1.csv")
    for person in persons:
        print(person)

My Output:

Traceback (most recent call last):
  File "C:/Users/Jason/untitled-2.py", line 61, in <module>
    for person in persons:
builtins.TypeError: 'NoneType' object is not iterable

Problem 3

As if that wasnt enough, now, I need to add a new function filter_people(people, status) that takes a list of people and a "status" string and returns a new list containing just the people from the original list whose health status equals the status parameter. Note that the function is a global function, not a method of the class Person.

The function filter_people(people, status) should only be about 6 lines of code, excluding comments. The maximum function length is set to 10 statements, as for the previous question.

Test

persons = read_people("people1.csv")
for status in ['Underweight', 'Normal', 'Overweight', 'Obese']:
    persons_with_status = filter_people(persons, status)
    print("People who are {}:".format(status))
    for person in persons_with_status:
        print(person)
    print()

Expected Result:

People who are Underweight:
Rambo Stallone (19) has a bmi of 14.75. Their status is Underweight.

People who are Normal:
Sharon Stone (14) has a bmi of 19.53. Their status is Normal.
Arnold Shwarnegger (70) has a bmi of 21.74. Their status is Normal.

People who are Overweight:
Rosie Donell (23) has a bmi of 26.99. Their status is Overweight.

People who are Obese:
Roly Polly (47) has a bmi of 53.35. Their status is Obese.

Where am I going wrong. I keep getting the following error:

builtins.TypeError: 'NoneType' object is not iterable

I need help with Problem 2 and Problem 3. Help!!!

2
  • is read_people supposed to return something...? because it doesn't seem to Commented Oct 5, 2018 at 12:47
  • 2
    BTW, Stack Exchange questions are supposed to contain one question per question. That makes them more useful for future readers. Commented Oct 5, 2018 at 13:03

2 Answers 2

2
def read_people(csv_filename):
    """reads file and sorts it then runs through a class"""
    lst = []
    final = []
    file = open(csv_filename, 'r')

    for row in file:
        print(row)
        lst.append(row)

You should return your list at the end of your function

Sign up to request clarification or add additional context in comments.

3 Comments

Yes, I think so ;)
can you add a print to show what contains row before your append?
@PM 2Ring was right your function is not in the appropriate place, check his answer
0

The read_people function should not be defined inside the Person class. It's a separate function that creates a list of Person instances from the file data, and then returns that list. Your read_people doesn't parse the file data, it doesn't create a Person from that data, and it doesn't return the list.

Here's a repaired version. To make my code self-contained, I read the file data from a list of strings, but it's easy to change it back to reading from the actual CSV file.

# A fake file
file = '''\
Rolly Polly,47,148.8,1.67
Rosie Donell,23,89.4,1.82
Rambo Stallone,19,59,2.0
Sharon Stone,14,50,1.6
Arnold Shwarnegger,70,59.2,1.65
'''.splitlines()


class Person:
    """Defines a Person class, suitable for use in a hospital context.
        Methods: bmi(), status()
    """
    def __init__(self, name, age, weight, height):
        """ Create a new Person object with the specified
            name, age, weight and height
        """
        self.name = name
        self.age = age
        self.weight = weight
        self.height = height

    def bmi(self):
        """ Return the body mass index of the person """
        return self.weight / (self.height * self.height)

    def status(self):
        """ Determine status """
        bmi = self.bmi()
        if bmi < 18.5:
            status = "Underweight"
        elif 18.5 <= bmi < 25:
            status = "Normal"
        elif 25 <= bmi < 30:
            status = "Overweight"
        elif bmi >= 30:
            status = "Obese"
        return status

    def __str__(self):
        """ Output data """
        answer = "{0} ({1}) has a bmi of {2:.02f}. Their status is {3}."
        return answer.format(self.name, self.age, self.bmi(), self.status())

def read_people(csv_filename):
    """reads file and sorts it then runs through a class"""
    lst = []
    #file = open(csv_filename, 'r')
    for row in file:
        name, age, weight, height = row.split(',')
        lst.append(Person(name, int(age), float(weight), float(height)))
    #file.close()
    return lst

persons = read_people("people1.csv")
for person in persons:
    print(person)

output

Rolly Polly (47) has a bmi of 53.35. Their status is Obese.
Rosie Donell (23) has a bmi of 26.99. Their status is Overweight.
Rambo Stallone (19) has a bmi of 14.75. Their status is Underweight.
Sharon Stone (14) has a bmi of 19.53. Their status is Normal.
Arnold Shwarnegger (70) has a bmi of 21.74. Their status is Normal.

Rather than using name, age, weight, height = row.split(',') to parse the file data, it would be better to use the standard csv module, but I suspect that for this assignment you aren't allowed to do that.

Your code for the Person class was mostly ok, but I've made a few minor adjustments to it.

Now see if you can figure out Problem 3. ;) If you get stuck, please ask a new question (you can link it to this question if you want).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.