Testing for an empty iterator in a Python for… loop
以下代码基于此配方。然而,配方的关键点——如果迭代器为空,它提供了一种在迭代器上中断迭代的方法——似乎在这里不起作用,而是以以下不需要的方式工作:
我如何确保:
- 如果get_yes_no_answer()==false,并且迭代器中还有两个或多个项,则不会跳过下一个_选项?
- 如果get_yes_no_answer()==false,并且迭代器中还有一个项目,my_func()将打印它并调用get_yes_no_answer()?
- 如果get_yes_no_answer()==false且迭代器中没有剩余项,是否触发except stopIteration子句?
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | def my_func(choice_pattern, input): # Search in input for some things to choose from. choice_iterator = choice_pattern.finditer(input, re.M) if not choice_iterator: print"No choices. Exiting..." sys.exit() else: # Show choices to the user. For each one, ask user for a yes/no response. If # choice accepted, return a result. Otherwise show user next choice. If no # choices accepted by user, quit. for choice in choice_iterator: print choice.group() # get_yes_no_answer() returns True or False depending on user response. if get_yes_no_answer(): return choice else: # Check if iterator is empty. If so, quit; if not, do something else. try: next_choice = choice_iterator.next() except StopIteration: print"No matches. Exiting..." sys.exit() else: choice_iterator = itertools.chain([next_choice], choice_iterator) |
你为什么这样做?为什么不只是:
1 2 3 4 5 6 7 8 9 | def get_choice(pattern, inpt): choices = pattern.finditer(inpt, re.M) if not choices: sys.exit('No choices') for choice in choices: print(choice.group(0)) if get_yes_no_answer(): return choice sys.exit('No matches') |
我不知道你输入的长度是多少,但我怀疑这值得麻烦。
您不需要检查迭代器是否为空。for循环将为您这样做,当迭代器为空时停止。就这么简单。
另外,在sys.exit()或返回之后,您不需要
完成后,您的代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | def my_func(choice_pattern, input): # Search in input for some things to choose from. choice_iterator = choice_pattern.finditer(input, re.M) if not choice_iterator: print"No choices. Exiting..." sys.exit() # Show choices to the user. For each one, ask user for a yes/no response. If # choice accepted, return a result. Otherwise show user next choice. If no # choices accepted by user, quit. for choice in choice_iterator: print choice # get_yes_no_answer() returns True or False depending on user response. if get_yes_no_answer(): return choice # Loop exited without matches. print"No matches. Exiting..." sys.exit() |
就是这样!
发生的是你在循环中,也得到下一个项目。结果是你实际上只显示每一秒的答案。
实际上,您可以更加简化它:
1 2 3 4 5 6 7 8 9 10 | def my_func(choice_pattern, input): choice_iterator = choice_pattern.finditer(input, re.M) if choice_iterator: for choice in choice_iterator: print choice if get_yes_no_answer(): return choice # If there is no choices or no matches, you end up here: print"No matches. Exiting..." sys.exit() |
迭代器几乎和任何序列类型一样被使用。你不需要把它和清单区别对待。
为什么这么复杂的方法?
我认为这应该是基本相同的:
1 2 3 4 5 6 7 8 9 10 | def my_func(pattern, data): choices = pattern.findall(data, re.M) while(len(choices)>1): choice = choices.pop(0) if get_yes_no_answer(): return choice else: choices.pop(0) else: return None |
请参阅这个问题中的成对迭代器。然后您可以检查最后一项,如:
1 2 3 4 5 6 7 8 | MISSING = object() for choice, next_choice in pairwise(chain(choice_iterator, [MISSING])): print(choice.group()) if get_yes_no_answer(): return choice.group() if next_choice is MISSING: print("No matches. Exiting...") sys.exit() |
在您展示的示例中,这似乎不是必需的。您不需要检查finditer是否返回迭代器,因为它总是返回迭代器。如果你找不到你想要的东西,你可以通过for循环:
1 2 3 4 5 6 7 8 9 | def my_func(choice_pattern, input): """Search in input for some things to choose from.""" for choice in choice_pattern.finditer(input, re.M): print(choice.group()) if get_yes_no_answer(): return choice.group() else: print("No choices. Exiting...") sys.exit() |