Как разбить цикл Python while из функции в цикле

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 

Я знаю, что могу поставить «if logic» непосредственно в цикле while, но я хочу, чтобы это было в функции. Есть ли способ разбить цикл while из функции, вызванной в цикле?

Обычно я это делаю:

 def getInput(): while True: yield raw_input("enter input: ") for input in getInput(): if input == 'exit': break result = useInput(input) 
  1. Поднимите исключение, которое вы можете обрабатывать вне цикла While
  2. Верните флаг, который должен быть захвачен вызывающим и соответствующим образом обработать. Обратите внимание, что "if logic" directly in the while loop, будет наиболее предпочтительным способом.

Python имеет классную функцию в генераторах – это позволяет вам легко создавать итерации для использования с циклом for , что упрощает такой тип кода.

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

Цикл for будет зацикливаться до тех пор, пока итератор не остановится, и итератор, который мы сделали, останавливается, когда пользователь вводит "exit" . Обратите внимание, что я немного обобщил это для простоты, вы можете жестко скопировать проверку с "exit" в генератор, но если вам нужно подобное поведение в нескольких местах, возможно, стоит сохранить его в общем.

Обратите внимание, что это также означает, что вы можете использовать его в понимании списка , что упрощает сбор списка результатов.

Изменить: В качестве альтернативы мы могли бы создать это с помощью 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: ")): ... 

Вы можете создать исключение и обработать его за пределами while … но это, вероятно, приведет к некоторому запутанному коду …

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

Намного лучше просто вернуть булевский флаг, а затем сломать или нет, в зависимости от значения этого флага. Если вы беспокоитесь, что у вас уже есть что-то, что вы хотите вернуть, не волнуйтесь – python с радостью позволит вашей функции вернуть несколько вещей:

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

Хорошо, если его просто эстетика не позволяет вам помещать его в цикл while, то любой из вышеперечисленных действий будет работать … не от поклонника try / except, хотя. Просто знайте, что не будет никакой разницы в производительности, если поместить его в свою собственную функцию. Вот тот, который, я считаю, также отвечает вашим требованиям 🙂

 # 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