Classes: Python . Exercises

Hello, I’m learning about classes in Python and I"m having trouble with this exercise. It’s not printing the expected result

Here’s the link: https://www.codecademy.com/paths/data-analyst/tracks/dacp-python-fundamentals/modules/dscp-python-classes/projects/ds-python-classes-project

class Patient: def __init__(self, name, age,sex, bmi, num_of_children, smoker): self.name = name self.age = age self.sex = sex self.bmi = bmi self.num_of_children = num_of_children self.smoker = smoker # add more parameters here patient1 = Patient("John Doe", 25, 1, 22.2, 0, 0) #print(patient1.bmi) def estimated_insurance_cost(self): estimated_cost = (250 * self.age - 128 * self.sex + 370 * self.bmi + 425 * self.num_of_children + 24000 * self.smoker - 12500) print(self.name + "'s estimated insurance cost is " + str(estimated_cost) + " dollars.", patient1.estimated_insurance_cost())

So, if we run the code in your codebyte, the output is

image

From that, I’d suspect that you intended the estimated_insurance_cost function to be included in the class. It isn’t. Can you see why not?

Hint:

You have an outdented line of code between the class definition and the function. Python uses indentation to determine scope. Your outdented line of code should probably be after the function. That would include the function in the class where it belongs.

3 Likes

Hello, thank you so much for getting back to me! I realized the issue with patient1 once you brought my attention to it so I’ve put it at the end so that estimated_insurance_cost stays in the class but now I’m getting a message that my print isn’t working because self isn’t defined which I don’t understand because i’ve defined it in "def estimated_insurance_cost(self)

class Patient: def __init__(self, name, age,sex, bmi, num_of_children, smoker): self.name = name self.age = age self.sex = sex self.bmi = bmi self.num_of_children = num_of_children self.smoker = smoker # add more parameters here #print(patient1.bmi) def estimated_insurance_cost(self): estimated_cost = (250 * self.age - 128 * self.sex + 370 * self.bmi + 425 * self.num_of_children + 24000 * self.smoker - 12500) patient1 = Patient("John Doe", 25, 1, 22.2, 0, 0) print(self.name + "'s estimated insurance cost is " + str(estimated_cost) + " dollars.", patient1.estimated_insurance_cost())

The issue is again with indentation. self refers to the current instance of the class, so references to self need to be inside the class as well. In this case it looks as though your print statement should be inside the estimated_insurance_cost(self): function.

1 Like

I see, I see. I’ve also notice I hadn’t put a \ before the 's in my print statement so I’ve added that and now I’m not getting error messages but i’m also not getting anything printed and I don’t see why.

class Patient: def __init__(self, name, age,sex, bmi, num_of_children, smoker): self.name = name self.age = age self.sex = sex self.bmi = bmi self.num_of_children = num_of_children self.smoker = smoker # add more parameters here #print(patient1.bmi) def estimated_insurance_cost(self): estimated_cost = (250 * self.age - 128 * self.sex + 370 * self.bmi + 425 * self.num_of_children + 24000 * self.smoker - 12500) patient1 = Patient("John Doe", 25, 1, 22.2, 0, 0) print(self.name + "\'s estimated insurance cost is " + str(estimated_cost) + " dollars.", patient1.estimated_insurance_cost())

The code you’ve shared produces no errors or output. What additional code did you run?

Some things I see that are problematic with what you’ve shared:

You are creating an instance of your Patient class inside the class itself inside the estimated_insurance_cost function. You probably meant for that to be outside of the class.

patient1 = Patient("John Doe", 25, 1, 22.2, 0, 0)

Then in your print statement, you are calling the function at the end of it:

print(self.name + "\'s estimated insurance cost is " + str(estimated_cost) + " dollars.", patient1.estimated_insurance_cost())
#                                                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                 

This is an example of recursion. In this case it causes a stack overflow error because the function will repeatedly call itself forever. You’ll learn about recursion later (if you haven’t already). It has its uses, but this is not a case where you want the function to call itself.

I’m assuming that what you want here is to create an instance of Patient and then call the estimated_insurance_cost function on that instance. Those tasks should occur outside of the class at the end of your code.

1 Like

I figured it out!!! Thank you so much.

class Patient: def __init__(self, name, age,sex, bmi, num_of_children, smoker): self.name = name self.age = age self.sex = sex self.bmi = bmi self.num_of_children = num_of_children self.smoker = smoker # add more parameters he def estimated_insurance_cost(self): estimated_cost = (250 * self.age - 128 * self.sex + 370 * self.bmi + 425 * self.num_of_children + 24000 * self.smoker - 12500) print("{}'s estimated insurance cost is {} dollars.".format(self.name, estimated_cost)) patient1 = Patient("John Doe", 25, 1, 22.2, 0, 0) patient1.estimated_insurance_cost()
1 Like

I’m trying to update the class so that users can upload lists of patient data rather than just individual numbers but i’m having some issues. I"m getting "AttributeError: ‘list’ object has no attribute ‘update_age’. Would be grateful if you could check it out1

class Patient: def __init__(self, patient): self.patient =patient for i in self.patient: self.name = self.patient[0] self.age = self.patient[1] self.sex = self.patient[2] self.bmi = self.patient[3] self.num_of_children = self.patient[4] self.smoker = self.patient[5] # add more parameters he def estimated_insurance_cost(self): try: estimated_cost = 250 * self.age\ - 128 * self.sex\ + 370 * self.bmi\ + 425 * self.num_of_children\ + 24000 * self.smoker \ - 12500 print("{patient_name}'s estimated insurance cost is {estimated_cost} dollars.".format(patient_name=self.name, estimated_cost=estimated_cost)) except: print("Are your values for sex, bmi, number of children and smoker all numeric?") def update_age(self, new_age): self.age= new_age print("{patient_name} is now {patient_age} years old.".format(patient_name=self.name, patient_age=self.age)) self.estimated_insurance_cost() def update_num_children(self, new_num_children): self.num_of_children= new_num_children if self.num_of_children==1: print("{patient_name} has {patients_n_of_children} child.".format(patient_name= self.name, patients_n_of_children =self.num_of_children)) else: print("{patient_name} has {patients_n_of_children} children.".format(patient_name= self.name, patients_n_of_children =self.num_of_children)) self.estimated_insurance_cost() def update_bmi(self, new_bmi): self.bmi = new_bmi print(self.name + "'s new updated BMI is: " + str(new_bmi)) self.estimated_insurance_cost() def update_smoking_status(self,new_smoking_status): self.smoker = new_smoking_status if new_smoking_status == 1: print(self.name + " is a smoker.") else: print(self.name + " quit smoking") self.estimated_insurance_cost() def patient_profile(self): patient_information={} patient_information["Name"]=self.name patient_information['Age']=self.age patient_information['Sex']=self.sex patient_information['Bmi']=self.bmi patient_information['Num_of_children']=self.num_of_children patient_information['Smoker']=self.smoker return patient_information #patient1 = Patient("John Doe", 25, "sex", 22.2, 0, 0) patient1 = ["John Doe", 25, 1, 22.2, 0, 0] john= Patient(patient1) print(john.name) patient1.update_age=["John Doe", 46, 1, 22.2, 0, 0] patient1.update_num_children= ["John Doe", 25, 1, 22.2, 5, 0] print(patient1.patient_profile())

Consider what you did here:

john= Patient(patient1)

When you try to execute this line:

patient1.update_age=["John Doe", 46, 1, 22.2, 0, 0]

What does patient1 refer to? It’s still a list:

patient1 = ["John Doe", 25, 1, 22.2, 0, 0]

Also, update_age and update_num_children are methods. The way you wrote them, they each accept a single parameter. How do you call such a method?

I’ve copied, and run your code. It works well once the issues above are addressed. Nice job!
You might consider giving your class a __repr__ or __str__ method for easy printing of each Patient instance rather than your current patient_profile method.

2 Likes

My update was succeful! Thanks!

1 Like

I was able to modify it and to make it print the updated age or other info but my patient_profile dictionary doesn’t work. I wasn’t able to make it read the list. I believe a regular instance method only takes one argument

class Patient: def __init__(self, patient): self.patient =patient for i in self.patient: self.name = self.patient[0] self.age = self.patient[1] self.sex = self.patient[2] self.bmi = self.patient[3] self.num_of_children = self.patient[4] self.smoker = self.patient[5] # add more parameters he def estimated_insurance_cost(self): try: estimated_cost = 250 * self.age\ - 128 * self.sex\ + 370 * self.bmi\ + 425 * self.num_of_children\ + 24000 * self.smoker \ - 12500 print("{patient_name}'s estimated insurance cost is {estimated_cost} dollars.".format(patient_name=self.name, estimated_cost=estimated_cost)) except: print("Are your values for sex, bmi, number of children and smoker all numeric?") def update_age(self, patient): self.age= self.patient[1] print("{patient_name} is now {patient_age} years old.".format(patient_name=self.name, patient_age=self.age)) self.estimated_insurance_cost() def update_num_children(self, new_num_children): self.num_of_children= new_num_children if self.num_of_children==1: print("{patient_name} has {patients_n_of_children} child.".format(patient_name= self.name, patients_n_of_children =self.num_of_children)) else: print("{patient_name} has {patients_n_of_children} children.".format(patient_name= self.name, patients_n_of_children =self.num_of_children)) self.estimated_insurance_cost() def update_bmi(self, new_bmi): self.bmi = new_bmi print(self.name + "'s new updated BMI is: " + str(new_bmi)) self.estimated_insurance_cost() def update_smoking_status(self,new_smoking_status): self.smoker = new_smoking_status if new_smoking_status == 1: print(self.name + " is a smoker.") else: print(self.name + " quit smoking") self.estimated_insurance_cost() def patient_profile(self): patient_information={} patient_information["Name"]=self.patient[0] patient_information['Age']=self.patient[1] patient_information['Sex']=self.patient[2] patient_information['Bmi']=self.patient[3] patient_information['Num_of_children']=self.patient[4] patient_information['Smoker']=self.patient[5] return patient_information #patient1 = Patient("John Doe", 25, "sex", 22.2, 0, 0) patient1 = ["John Doe", 25, 1, 22.2, 0, 0] patient1=["John Doe", 46, 1, 22.2, 0, 0] patient1= ["John Doe", 25, 1, 22.2, 5, 0] john= Patient(patient1) print(john.num_of_children) print(patient1.patient_profile())

Actually it works fine, but you need to call an instance method on an instance of the class. patient1 is not an instance of Patient. Compare your last 2 lines of code. In the first print you retrieve the num_of_children property of the Patient instance, john. In the last print you attempt to call a method that belongs to your Patient class on a list rather than on the Patient instance john.

2 Likes