在Python for for循环中测试空迭代器

时间:2009-09-29 11:27:15

标签: python exception iterator conditional

以下代码基于this recipe。但是,配方的关键点 - 如果迭代器为空,它提供了一种在迭代器上突破迭代的方法 - 在这里似乎不起作用,而是以下列不期望的方式运行:

  1. 如果 get_yes_no_answer()== False 并且迭代器中还剩下两个或更多项目,则跳过 next_choice ,而不是在下一次迭代中被选中。< / LI>
  2. 如果 get_yes_no_answer()== False 并且迭代器中剩余的项目少于两个, my_func()将返回None。
  3. 我如何确保:

    • 如果 get_yes_no_answer()== False 并且迭代器中还有两个或更多项目, next_choice 被跳过?
    • 如果 get_yes_no_answer()== False 并且迭代器中还剩下一个项目, my_func()会打印它并调用 get_yes_no_answer() <?/ LI>
    • 如果 get_yes_no_answer()== False 并且迭代器中没有剩余项目,则触发除StopIteration 子句?

    以下是代码:

    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)
    

4 个答案:

答案 0 :(得分:3)

你为什么这样做呢?为什么不呢:

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')

我不知道你输入的长度是多少,但我怀疑这是值得的。

答案 1 :(得分:1)

您无需检查迭代器是否为空。 for循环将为您执行此操作,并在迭代器为空时停止。就这么简单。

此外,在sys.exit()或return之后不需要else

完成后,您的代码如下所示:

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()

就是这样!

你在循环中会发生什么,获得下一个项目。结果是你实际上只显示每一秒的答案。

事实上,您可以进一步简化它:

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()

迭代器几乎与任何序列类型一样使用。您不需要以不同的方式对待它。

答案 2 :(得分:0)

请参阅this question中的成对迭代器。然后,您可以检查最后一项:

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循环:

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()

答案 3 :(得分:0)

为什么这么复杂的方法?

我认为这应该做的几乎相同:

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