在 Python 中重做 for 循环迭代 [英] Redo for loop iteration in Python

查看:39
本文介绍了在 Python 中重做 for 循环迭代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python 是否具有某些语言中存在的重做"语句的形式?

Does Python have anything in the fashion of a "redo" statement that exists in some languages?

(redo"语句是一个语句(就像break"或continue"一样)影响循环行为——它在最内层循环的开始处跳转并再次开始执行.

(The "redo" statement is a statement that (just like "break" or "continue") affects looping behaviour - it jumps at the beginning of innermost loop and starts executing it again.)

推荐答案

不,Python 不直接支持 redo.一种选择是涉及嵌套循环的有点可怕的东西,例如:

No, Python doesn't have direct support for redo. One option would something faintly terrible involving nested loops like:

for x in mylist:
    while True:
        ...
        if shouldredo:
            continue  # continue becomes equivalent to redo
        ...
        if shouldcontinue:
            break     # break now equivalent to continue on outer "real" loop
        ...
        break  # Terminate inner loop any time we don't redo

但这意味着在redo-able"块中break外循环是不可能的,除非求助于异常、标记变量或打包整个事情作为一个函数.

but this mean that breaking the outer loop is impossible within the "redo-able" block without resorting to exceptions, flag variables, or packaging the whole thing up as a function.

或者,您可以使用直接的 while 循环来复制 for 循环为您所做的事情,明确地创建和推进迭代器.它有它自己的问题(continue 在默认情况下实际上是 redo,您必须显式推进迭代器以获得真正的"continue),但是它们并不可怕(只要您注释 continue 的使用,以明确您打算 redocontinue,以避免混淆维护者).要允许 redo 和其他循环操作,您可以执行以下操作:

Alternatively, you use a straight while loop that replicates what for loops do for you, explicitly creating and advancing the iterator. It has its own issues (continue is effectively redo by default, you have to explicitly advance the iterator for a "real" continue), but they're not terrible (as long as you comment uses of continue to make it clear you intend redo vs. continue, to avoid confusing maintainers). To allow redo and the other loop operations, you'd do something like:

# Create guaranteed unique sentinel (can't use None since iterator might produce None)
sentinel = object()
iterobj = iter(mylist)  # Explicitly get iterator from iterable (for does this implicitly)
x = next(iterobj, sentinel)  # Get next object or sentinel
while x is not sentinel:     # Keep going until we exhaust iterator
    ...
    if shouldredo:
        continue
    ...
    if shouldcontinue:
        x = next(iterobj, sentinel)  # Explicitly advance loop for continue case
        continue
    ...
    if shouldbreak:
        break
    ...
    # Advance loop
    x = next(iterobj, sentinel)

上述也可以用 try/except StopIteration: 代替带有 sentinel<的两个参数 next/code>,但用它包装整个循环可能会导致 StopIteration 的其他来源被捕获,并且在有限的范围内为内部和外部 next 调用正确执行此操作将是极其丑陋(比基于 sentinel 的方法更糟糕).

The above could also be done with a try/except StopIteration: instead of two-arg next with a sentinel, but wrapping the whole loop with it risks other sources of StopIteration being caught, and doing it at a limited scope properly for both inner and outer next calls would be extremely ugly (much worse than the sentinel based approach).

这篇关于在 Python 中重做 for 循环迭代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆