Python beginner needs help with Medical Insurance Project Extra Step

Hi all,
I am having trouble with the first part of the project extra challenge that says:
“Modify the calculate_insurance_cost() function so that it returns two values – the output message and the estimated cost.”

I found this posting from 2 years ago when a user asked a similar question, but I’m still having trouble getting my code to work. I keep getting a NameError when I call the output message value outside of the calculate_insurance_cost function. Thank you so much in advance for your help!

https://discuss.codecademy.com/t/python-functions-medical-insurance-project-task-13-extra/552712/26

# Create calculate_insurance_cost() function below: def calculate_insurance_cost(name,age, sex, bmi, num_of_children, smoker): estimated_cost = 250*age - 12*sex + 370*bmi + 425*num_of_children + 24000*smoker - 12500 message = "The estimated insurance cost for " + name + " is " + str(estimated_cost) + " dollars." return(estimated_cost, message) # Estimate Maria's insurance cost maria_insurance_cost = calculate_insurance_cost("Maria",28,0,26.2,3,0) print(message) # Estimate Omar's insurance cost omar_insurance_cost = calculate_insurance_cost("Omar",35,1,22.2,0,1)

This is b/c message is a locally defined variable and you’re trying to access it outside the function scope. See, Handling NameError Exception in Python - GeeksforGeeks
and, here: https://pythongeeks.org/namespaces-and-scope-in-python/

Rather than defining message inside the function, could you use something else, like print() & then return?
You could maybe do something like:

Summary
def calculate_insurance_cost(name, age, sex, bmi, num_of_children, smoker):
  estimated_cost = 250*age - 128*sex + 370*bmi + 425*num_of_children + 24000*smoker - 12500
  
  print("The estimated insurance cost for " + name + "is "   + str(estimated_cost) + " dollars. ")
  
  return estimated_cost

# Estimate Maria's insurance cost
maria_insurance_cost = calculate_insurance_cost(name = "Maria", age = 28, sex = 0, bmi = 26.2, num_of_children = 3, smoker = 0)

Thanks Lisa! The challenge was to modify the function so it returned two values . Sorry I didn’t include a link to the project in my original post but this is it. The part I am having trouble with is 13 bullet 1. I guess I understand how to add the second value in the return statement, but can’t figure out how folks in another post were able to print the message outside of the function:

Sep '21

“I think for the first part of this task it would make more sense if the function did not print the output message by default. So you return the message and the estimated cost, you then have the option of printing the returned message outside the function if you want to. Since it’s an extended task I don’t think you need to worry about whether your example is particularly useful, just be aware that you can do this.”

https://www.codecademy.com/journeys/data-scientist-aly/paths/dsalycj-22-data-science-foundations/tracks/dsalycj-22-python-fundamentals-for-data-science-part-i/modules/dsf-python-functions-594ffb4a-754f-4a54-9790-b8a476b2a120/projects/ds-python-functions-project

Thanks for the link. I remembered it b/c I completed it a long time ago.
The code that I posted above does return the two things–the message and the estimated cost.

The estimated insurance cost for Maria is 5469.0 dollars.

You have return(estimated_cost, message) which stylistically may as well be return estimated_cost, message. You’re effectively returning a two element tuple in that case. If you don’t know tuples just think list but you can’t alter it (no reassign or append/remove). If that’s too confusing for now return a list explicitly e.g. return [estimated_cost, message] that you might be more familiar with.

If the requirements say “return” that’s what I’d go for.


As a general rule don’t think about the exact names used inside a function but the objects being returned instead. Here the name message exists only in the function. You pass the object message referred to back to the caller, not the name message itself. With return think of almost literally returning an object (or a value if you don’t know objects yet); not names.

In the example below the end result of calling the two functions below is identical. You get an integer 3, the x has zero meaning outside the function.

def f():
    x = 3
    return x
def g():
    return 3


a = f()
b = g()
a == b

Back to handling the output of your function.

You bind the returned tuple to maria_insurance_cost and that’s the only place you can access the returned objects. If you printed it you’d see something like (4000, "The estimated insurance cost..."). So after the call you have access to the newly created objects, just not by the names they happened to use inside a function.

You can do two things. Either access the relevant elements of this tuple e.g.

print(maria_insurance_cost[1])

Or you can change the bit where you call your function to unpack the tuple when you assign it e.g.

maria_insurance_cost, maria_message = calculate_insurance_cost("Maria",28,0,26.2,3,0)
print(maria_message)

This takes the two elements of your tuple and applies them separately to the names of the left. It’s the same behaviour as a, b = 1, 2 where a is assigned to 1 and b to 2.

1 Like

(for step 13) The directions state: " * Modify the calculate_insurance_cost()function so that it returns two values – the output message and the estimated cost." Prior steps asked you to create variables for Maria, Omar, and yourself.
Which to me, says you want two items in one sentence: “the estimated insurance cost for --name goes here-- is: $whatever dollar amount is calculated.”

Which is what the code I supplied above does…
(including utilizing print() and return inside the function which is in step 3.)

1 Like

OHHHH That clarifies some of the other posts I was reading as well as my own question. Thanks so much for the help! Turns out I misunderstood/misread the question.

1 Like

Thanks so much! I def need to reread this a couple times. It’s been over 10 years since I took a python class college so I vaguely remember the concept of tuples but definitely remembered local vs global variables and thought that was the problem I was experiencing. Turns out I was misinterpreting the question but I know tuples is right around the corner so this will be very helpful going forward! Appreciate how helpful this community is!

On the off-chance you encounter another problem saying “return two values” I’d probably assume a tuple. I know this one isn’t tested but they’re rarely vague in their terminology because most challenges are tested. Mistakenly conflating return with print causes enough issues for learners as-is. The wording here should probably be tightened up to avoid confusion as many learners myself included read “return two values” as a a literal requirement.

In this particular instance I have no idea what they mean (they stripped tuples from the early syllabus so it’s less likely they actually meant a tuple); since it’s an extra challenge I don’t suppose it matters much :slightly_smiling_face: . The reason I commented on the print in the originally quoted message from a couple of years back is because printing and returning from the same function is normally bad design so task 3 or wherever it is originally used was probably not a good choice. It should ideally be a function (returns something) or a procedure (has a side effect); not both. That’s why I dislike the original task that did both, I/O is a side effect and probably should’ve been in its own function or otherwise. For passing lessons do whatever you need to do but for your own projects I’d suggest keeping side effects separated from return whenever possible (do one or the other in def, not both).

1 Like

That’s great advice and I will definitely keep that in mind! Thanks!