Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Python Basics Functions and Looping Raising Exceptions

I am confused about the raise function

What exactly is the "raise" function doing?

I don't understand why we have to move the line: amount_due = split_check(total_due, number_of_people) within the try block. If we enter zero, for example, shouldn't that "raise" the exception ValueError, thus prompting the except to print "Oh no!...etc" and make that line irrelevant?

2 Answers

boi
boi
14,241 Points

"the else: block should only run if the try: block does not prompt the except: block. So, the else block should only run if there is no ValueError"

Yes, Correct

"However, before moving the referenced line of code within the try block, number_of_people should register as less than or equal to 1, prompting ValueError to be raised, and therefore running the except: block and not the else: block. So it should never deliver the traceback message because the line "amount_due = split_check(total_due, number_of_people)" should never run. Help me understand where I'm going wrong"

Ok, let me first declare the referenced line;

amount_due = split_check(total_due, number_of_people) #This is the referenced line

Alright, say the referenced line is in the else block, and now you run the code.

Running the code ;

import math #First line of code, the program will import math module

def split_check(total, number_of_people):# This is a function, and the program does NOT execute the function if 
                                       # there is NO call, so it will move forward to the next line of code and 
    if number_of_people <=1:  # when this function is called, it will come back here and run this function
        raise ValueError("More than 1 person is required to split the check")     

    return math.ceil(total / number_of_people)

Read the comments carefully, Now the program will go to the next step ( Python executes code in sequence).

next step;

try:    
    total_due = float(input("What is the total?  ")) # Here the program will prompt you for an input, say u give it 100
                                                                                 # the input 100 will be stored in the variable total_due

   number_of_people = int(input("How many people?  ")) # Here the program will prompt you for input again, say you
                                                                                               # give it 0 or 1, the input will be stored in number_of_people
# NOTHING actually happened in the Try block but only values have been stored, so the program moves to the next step
# and the except block is SKIPPED entirely 

except ValueError as err:  #SKIPPED        
    print("Oh no! That's not a valid value. Try again...")
    print(err)

else:  # After the try block the program comes to the else block because the except block never ran or executed.
    amount_due = split_check(total_due, number_of_people) # NOW a function is called here, so the program goes to the
                                                                                                    # function block, which is at the top.
    print("Each person owes ${}".format(amount_due)) 

Now the program will go through the function block which is the amount_due = split_check(total_due,number_of_people)

now going through the function below;

def split_check(total, number_of_people):
    if number_of_people <=1:  # The program checks what value does "number_of_people" have.
#we gave the number_of_people a value of 1 or 0, since the condition is TRUE the program executes the IF block.

        raise ValueError("More than 1 person is required to split the check")  #Here it finds the "raise ValueError".
# Since the "raise ValueError" executed the program ENDS and gives a traceback with the following message,
#  ValueError : "More than 1 person is required to split the check"
    return math.ceil(total / number_of_people)

The End

I hope this gave you some clarification.

Thank you so much! I understand now.

boi
boi
14,241 Points

Glad it helped, you could mark the answer as "Best Answer" to help others be aware that the question has been answered.

boi
boi
14,241 Points

Hey Ben!

let's break it down slowly. Below is the Craig code

import math


def split_check(total, number_of_people):
    if number_of_people <=1:  # A condition is set here, and if the condition is "True", A ValueError will be raised.
        raise ValueError("More than 1 person is required to split the check")

     #if the above condition is "False" the below code will execute.  
    return math.ceil(total / number_of_people)

In simple words, the "raise" function will give out a ValueError with the message " More than 1 person is required to split the check" if the number of people is less than or equal to 1.

Now for the second part of your question.

import math


def split_check(total, number_of_people):
    if number_of_people <=1:
        raise ValueError("More than 1 person is required to split the check")

    return math.ceil(total / number_of_people)

try:
    total_due = float(input("What is the total?  "))
    number_of_people = int(input("How many people?  "))
    amount_due = split_check(total_due, number_of_people)
except ValueError as err:
    print("Oh no! That's not a valid value. Try again...")
    print(err)
else:

    print("Each person owes ${}".format(amount_due))

The reason that this line: amount_due = split_check(total_due, number_of_people) is moved within the try block is to handle the error properly.

If the line: amount_due = split_check(total_due, number_of_people) is not placed in the try block it would "raise" an error but with all the Traceback nonsense.

for example:

import math


def split_check(total, number_of_people):
    if number_of_people <=1:
        raise ValueError("More than 1 person is required to split the check")

    return math.ceil(total / number_of_people)

try:
    total_due = float(input("What is the total?  "))
    number_of_people = int(input("How many people?  "))
    # removed the line from here
except ValueError:
    print("Oh no! That's not a valid value. Try again...")

else:
    amount_due = split_check(total_due, number_of_people)
    print("Each person owes ${}".format(amount_due)) #placed the line here

# In the python shell, running the code!!!

what is the total?  #input 100

how many people? #input 0

#output 
Traceback (most recent call)
File "Check_please"Traceback (most recent call last):                                                               
  File "check_please.py", line 18, in <module>                                                   
    amount_due = split_check(total_due, number_of_people)                                        
  File "check_please.py", line 6, in split_check                                                 
    raise ValueError("More than 1 person is required to split the check")                        
ValueError: More than 1 person is required to split the check 

Do you see all that Traceback nonsense, to avoid this you put the line: amount_due = split_check(total_due, number_of_people) into the try block so that the error can be handled properly

import math


def split_check(total, number_of_people):
    if number_of_people <=1:
        raise ValueError("More than 1 person is required to split the check")

    return math.ceil(total / number_of_people)

try:
    total_due = float(input("What is the total?  "))
    number_of_people = int(input("How many people?  "))
    amount_due = split_check(total_due, number_of_people)

except ValueError as err:
    print("Oh no! That's not a valid value. Try again...")
    print(err)
else:

    print("Each person owes ${}".format(amount_due)) 

# In the python shell, running the code!!!

what is the total?  #input 100

how many people? #input 0

#output                                                                              
Oh no! That's not a valid value. Try again...                                                    
More than 1 person is required to split the check 

See the error messages are showing without that traceback nonsense

I hope you got at least some idea.

Hi. Thanks so much for the in-depth response. I'm still a little confused though - so, from my understanding, the else: block should only run if the try: block does not prompt the except: block. So, the else block should only run if there is no ValueError. However, before moving the referenced line of code within the try block, number_of_people should register as less than or equal to 1, prompting ValueError to be raised, and therefore running the except: block and not the else: block. So it should never deliver the traceback message because the line "amount_due = split_check(total_due, number_of_people)" should never run. Help me understand where I'm going wrong