Cómo romper un bucle Python while desde una función dentro del bucle

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 

Sé que puedo poner el “if logic” directamente en el bucle while, pero quiero que esté en la función. ¿Hay una manera de romper un bucle while desde una función llamada en el bucle?

Generalmente hago esto:

 def getInput(): while True: yield raw_input("enter input: ") for input in getInput(): if input == 'exit': break result = useInput(input) 
  1. Genere una excepción que pueda manejar fuera del bucle While
  2. Devuelva una bandera para ser capturada por la persona que llama y maneje en consecuencia. Tenga en cuenta que "if logic" directly in the while loop, , sería la forma más preferida.

Python tiene una característica interesante en los generadores, que le permiten producir fácilmente los rendimientos para usar con un bucle for , que puede simplificar este tipo de código.

 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"): ... 

El bucle for repetirá hasta que el iterador se detenga, y el iterador que hicimos se detiene cuando el usuario ingresa "exit" . Tenga en cuenta que lo he generalizado un poco, por simplicidad, podría codificar la comprobación contra la "exit" en el generador, pero si necesita un comportamiento similar en algunos lugares, puede valer la pena mantenerlo en general.

Tenga en cuenta que esto también significa que puede usarlo dentro de una lista de comprensión , lo que facilita la creación de una lista de resultados también.

Edit: Alternativamente, podríamos construir esto con 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: ")): ... 

Puede generar una excepción y manejarla fuera de while … pero eso probablemente resultará en un código confuso …

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

Es MUCHO mejor devolver solo una bandera booleana y luego romperla o no dependiendo del valor de esa bandera. Si le preocupa que ya tiene algo que desea devolver, no se preocupe: python permitirá que su función regrese más de una cosa:

 def func() ... return something,flag while True: something,flag = func() if flag: break 

Bueno, si su justa estética no le permite ponerlo en el bucle while, entonces cualquiera de los anteriores funcionará … no es un fanático del try / excepto uno. Solo sé que no va a haber ninguna diferencia de rendimiento, puesto que lo tiene en su propia función. Aquí hay uno que creo que también cumple con sus requisitos 🙂

 # 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