Reputation: 5759
I have a while
loop that is reading user input. But I want the user to be able to break the while
loop at any point, so they can go back to a main menu.
At the moment this is the only way I can do it (if statements after every point that the user may have typed '--back'. The menu.code is returned from the menu.parse function if it is changed. But then the while loop has to completely finish before it's new menu code takes effect. Is there a way of doing this without all the if statements?
menu
is a class, and there are a couple of others. Below is a section from the main loop.
Some of the menu class:
class Menu:
def __init__(self):
self.code = 'main'
self.codememory = []
def exit(self, input):
if input == '--exit':
sys.exit()
def back(self, input):
if input == '--back':
if 'main' in self.codememory:
print "should be going back"
print self.code
self.code = self.codememory.pop()
print self.code
def move(self, input):
if input == '--new':
self.codememory.append(self.code)
self.code = 'new'
if input == '--main':
self.codememory.append(self.code)
self.code = 'main'
if input == '--help':
self.codememory.append(self.code)
self.code = 'help'
def select(self, input):
if input in string.digits:
input = int(input)
if input == 1:
self.codememory.append(self.code)
self.code = 'new'
if input == 2:
self.codememory.append(self.code)
self.code = 'test'
def header(self, title):
os.system('clear')
print "-------------------"
print title.upper()
print "-------------------"
print ""
def parse(self, input):
self.exit(input)
self.back(input)
if self.code == 'new':
return input.lower().decode('utf-8')
############################
menu = Menu()
while 1:
...
while menu.code == 'new':
menu.header('save word')
key = menu.parse(raw_input("Norwegain: "))
while key in dict.keys:
print "word already Saved in Dictionary"
key = menu.parse(raw_input("Norwegain: "))
if menu.code == 'new':
val = menu.parse(raw_input("English: "))
if menu.code == 'new':
syn = menu.parse(raw_input("Synonym: "))
if menu.code == 'new':
ant = menu.parse(raw_input("Antonym: "))
while menu.code == 'main':
...
Upvotes: 1
Views: 2235
Reputation: 24157
Raise an exception to exit the loop. This is a common enough trick in Python and the way you describe your problem makes me believe it is actually some kind of exception you are willing to manage.
Code may look like below:
class OutMainLoop(Exception):
pass
while 1:
try:
while menu.code == 'new':
blah ...
while key in dict.keys:
blah ...
if some_condition:
raise OutToMainLoop()
blah ...
val = menu.parse(raw_input("English: "))
except OutToMainLoop:
pass
But in this case it would certainly be even more natural to raise the exception from inside the menu class.
It very easy to do in Python. The Drawback is that is makes the code flow slightly harder to follow, but your example really looks like a legitimate use of an Exception.
Upvotes: 1
Reputation: 27038
To break out of multiple loops in Python, wrap the loops in a function and return from it when you would like to leave:
while 1:
def donew():
while menu.code == 'new':
blah ...
while key in dict.keys:
blah ...
if some_condition: return
blah ...
val = menu.parse(raw_input("English: "))
donew()
Upvotes: 3
Reputation: 5420
With this particular code, @kriss' suggestion to use exceptions is probably reasonable. Going a little more meta, you may want to look into state machines, though. It looks like your application is essentially a state machine, and, by using a state machine to handle transitions from one state to another, you could make your code much easier to follow and, more importantly, much easier to come back to in six months when somebody wants to add another command to it.
Upvotes: 1