3
while True:
    input = raw_input("enter input: ")
    result = useInput(input)

def useInput(input):
    if input == "exit":
        break   #return 0 / quit / etc.. i want to break the while loop from within this function

I know I can put the "if logic" directly in the while loop, but I want it to be in the function. Is there a way to break a while loop from within a function called in the loop?

alnafie
  • 10,558
  • 7
  • 28
  • 45
  • 1
    Is this just proof of concept, because the logic is very convoluted for what you're trying to do? – Hoopdady Jan 25 '13 at 14:09
  • The idea is that the function should handle/process/format the input then return the result, BUT for some keywords (like "exit" or "pass") I need to affect the while loop by somehow calling "break" or "continue". Aesthetically, I didn't like the idea of having all of these exceptions/keywords directly in the loop. But I am new to all this, so perhaps I just don't know the "proper" style to do it.. – alnafie Jan 25 '13 at 17:37

5 Answers5

3
  1. Raise an exception, that you can handle outside the While loop
  2. Return a flag to be captured by the caller and handle accordingly. Note, "if logic" directly in the while loop,, would be the most preferred way.
Abhijit
  • 62,056
  • 18
  • 131
  • 204
2

Python has a cool feature in generators - these allow you to easily produce iterables for use with a for loop, that can simplify this kind of code.

def input_until(message, func):
    """Take raw input from the user (asking with the given message), until 
    when func is applied it returns True."""
    while True:
        value = raw_input(message)
        if func(value):
            return
        else:
            yield value

for value in input_until("enter input: ", lambda x: x == "exit"):
    ...

The for loop will loop until the iterator stops, and the iterator we made stops when the user inputs "exit". Note that I have generalised this a little, for simplicity, you could hard code the check against "exit" into the generator, but if you need similar behaviour in a few places, it might be worth keeping it general.

Note that this also means you can use it within a list comprehension, making it easy to build a list of results too.

Edit: Alternatively, we could build this up with itertools:

def call_repeatedly(func, *args, **kwargs):
    while True:
        yield func(*args, **kwargs)

for value in itertools.takewhile(lambda x: x != "exit", 
                                 call_repeatedly(raw_input, "enter input: ")):
    ...
Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
1

I usually do this:

def getInput():
    while True:
        yield raw_input("enter input: ")

for input in getInput():
    if input == 'exit': 
        break
    result = useInput(input)
Jochen Ritzel
  • 104,512
  • 31
  • 200
  • 194
0

You can raise an exception and handle it outside of while ... but that will likely result in some confusing code ...

def useInput(in_):
    if in_ == "exit":
        raise RuntimeError
try:
    while True:
        input = raw_input("enter input: ")
        result = useInput(input)

except RuntimeError:
    pass

It's MUCH better to just return a boolean flag and then break or not depending on the value of that flag. If you're worried that you already have something you want to return, don't fret -- python will happily let your function return more than one thing:

def func()
    ...
    return something,flag

while True:
    something,flag = func()
    if flag:
        break
mgilson
  • 300,191
  • 65
  • 633
  • 696
0

Well if its just aesthetics thats keeps you from putting it in the while loop then any of the above would work... not of fan of the try/except one though. Just know there isn't going to be any performance difference putting it in its own function though. Here's one that I believe also meets your requirements :-)

# you have to define the function first if your while isn't in a function
def UseInput():
   input = raw_input("enter input: ")
   if input == "exit":
      return False
   elif input == "pass":
      return True


   # Do stuff
   return True


while UseInput():
   pass
Hoopdady
  • 2,296
  • 3
  • 25
  • 40