Search code examples
pythonwhile-loopflags

Python While loop breakout issues


The question I have is about the flag I have here for the while loop. This works but not like I think it should. I assume I'm not understanding something so if someone is able to explain, that would be great.

From my understanding this should break out of the loop as soon as one of my conditionals is met. So if I input 'q' it should break out and stop the loop. But what happens is it keeps going through the loop and then it breaks out. so it goes through the last prompt and prints the exception.

(Python version is 3.8.5)

# Statement that tells the user what we need.
print("Enter two numbers and I will tell you the sum of the numbers.")
# Lets the user know they can press 'q' to exit the program.
print("Press 'q' at anytime to exit.")

keep_going = True

# Loop to make the program keep going until its told to stop.
while keep_going:
    # Prompt for user to input first number and store it in a variable.
    first_number = input("First number: ")
    # Create a break when entering the first number.
    if first_number == 'q':
        keep_going = False
    # Prompt for user to input second number and store it in a variable.
    second_number = input("Second number: ")
    # Create a break when entering the second number.
    if second_number == 'q':
        keep_going = False
    # Exception for non integers being input "ValueError"
    try:
        # Convert input to integers and add them. 
        # storing the answer in a variable.
        answer = int(first_number) + int(second_number)
    except ValueError:
        # Tell the user what they did wrong.
        print("Please enter a number!")
    else:    
        # Print the sum of the numbers
        print(f"\nThe answer is: {answer}")

Using this code it breaks out right away like I expect it to.

while True:
    first_number = input("First number: ")
    if first_number == 'q':
        break
    second_number = input("Second number: ")
    if second_number == 'q':
        break

I just would like to understand what the difference is and if thats how it should work. I feel like I'm missing something or misunderstanding something.


Solution

  • The condition of the while loop is only checked between iterations of the loop body, so if you change the condition in the middle of the loop, the current iteration will finish before the loop terminates. If you want to break a loop immediately, you need to either break (which automatically breaks the loop regardless of the condition) or continue (which jumps to the next iteration, and will therefore terminate the loop if the condition is no longer true).

    Using while True: with a break when you want to stop the loop is generally much more straightforward than trying to control the loop by setting and unsetting a flag.

    FWIW, rather than copying and pasting the code to input the two numbers, and have two different ways to break out of the loop, I might put that all into a function and break the loop with an Exception, like this:

    print("Enter two numbers and I will tell you the sum of the numbers.")
    print("Press 'q' at anytime to exit.")
    
    
    def input_number(prompt: str) -> int:
        """Ask the user to input a number, re-prompting on invalid input.
        Exception: raise EOFError if the user enters 'q'."""
        while True:
            try:
                number = input(f"{prompt} number: ")
                if number == 'q':
                    raise EOFError
                return int(number)
            except ValueError:
                print("Please enter a number!")
    
    
    while True:
        try:
            numbers = (input_number(n) for n in ("First", "Second"))
            print(f"The answer is: {sum(numbers)}")
        except EOFError:
            break
    

    This makes it easier to extend the program to handle more than two inputs; try adding a "Third" after where it says "First" and "Second"! :)