You could just delete break
from your code if you fixed your loop condition, changing:
while (prompt != "YES" or prompt != "NO"):
which is always true ("YES" is not equal to "NO", so the second test is true whenever the first one is false, so the loop condition is always true), with either:
while prompt != "YES" and prompt != "NO":
which is the minimal change to fix the logic (so it stops if it's equal to either value, rather than only when it's equal to both), or for a more English readability:
while prompt not in ("YES", "NO"):
which doesn't have the tricks of how !=
and and
/or
interact in boolean logic to worry about. Either way, after fixing the test, the code will work as written without the need for break
at all.
To answer the broader question, the only alternatives to break
are:
- Careful use of tests to ensure the loop condition itself terminates when desired, and no code after the condition becomes true that should only execute when false is actually executed (this is what the minimal fix described above does)
- Using
return
in a function (requires factoring the loop out of the function it is in)
- Using an exception and
try
/except
to jump out of the loop.
Not coincidentally, these are also your options when you need to break
out of multiple levels of a nested loop (Python has no break
that can break an arbitrary number of loops). #1 is frequently unpythonic (especially if it relies on flag variables; in your case, it's okay, just mildly redundant on the tests), as is #3, so if your code can't use break
, and can't be restructured to avoid the need for it, #2 is usually the best solution, especially in complex cases.
Personally, I usually wouldn't put the handling of valid cases in the loop at all, leaving the loop to run and handle only invalid cases (which can occur 0-infinity times), with the valid cases handled after the loop is complete, exactly once.
A simple solution available on Python 3.8+ is to use the walrus operator (assignment expression for boring types) and just have the loop run until the result is valid, removing the handling for valid inputs from the loop entirely, putting them outside/after the loop entirely, so for your specific problem the end result would look like:
while (prompt := input("Are you ready?(YES/NO): ")) not in ("YES", "NO"):
print("Error, not a valid input")
if prompt == "YES":
print("Great!")
else: # No need for elif; only "YES" or "NO" would exit loop without throwing exception
print("How can I help?")
Pre-3.8, you could still do the same thing, the while
is just a little uglier (more repeated code):
prompt = input("Are you ready?(YES/NO): ")
while prompt not in ("YES", "NO"):
print("Error, not a valid input")
prompt = input("Are you ready?(YES/NO): ")
Bonus, with no particular increase in code complexity, you drop from 9-11 lines of code in your current design (9 without break
or explicit flag, 11 with) to 6-8 lines (6 with walrus, 8 without). With the walrus, it's strictly better; no code is repeated, no tests are repeated multiple times per loop, the loop is kept very simple.