在 Python 中跳出嵌套循环的 5 种方法

2023-12-29 23:16:53

在 Python 中跳出嵌套循环的 5 种方法(5 Ways To Break Out of Nested Loops in Python)


我们都知道,Python 是一种优雅的编程语言。但任何事物都有弱点。有时,Python 并不那么优雅。

例如,当我们需要跳出嵌套循环时如下:

for a in list_a:
    for b in list_b:
        if condition(a,b):
            break

break 关键字keyword只能帮助我们跳出最内层的循环inner-most loop。我们能直接同时跳出两个嵌套循环two nested loops吗?Python 中是否有一些内置关键字built-in keywords或技巧tricks?

遗憾的是,该操作没有内置支持no built-in support。

俗话说:“比较是快乐的小偷comparison is the thief of joy”。Python 做不到这一点,但其他语言可以,比如 PHP:

foreach ($a_list as $a)
{
    foreach ($b_list as $b)
    {
        if (condition($a, $b))
        {
            break 2; //break out of 2 loops
        }
    }
}

在 PHP 中, break 关键字接受一个可选的数字,该数字决定了要跳出多少个嵌套循环nested loops。默认值为 1 ,表示跳出最内层的循环inner-most loop。

这是一个非常简洁明了的解决方案。PHP 在这里确实更加优雅。

但这并不意味着我们必须现在就开始学习 PHP。因为 Python 非常灵活,我们有很多其他方法可以在没有语法支持的情况下获得相同的结果。

本文将介绍 Python 中跳出嵌套循环break out of nested loops的 5 种方法。最后,它还会提到如何在可能的情况下避免嵌套循环问题。希望您在阅读后能重拾对 Python 的信心。

1. 添加标志变量 Add a Flag Variable

这是一个有效的解决方案effective solution。我们定义一个变量variable,并将其作为标志flag。下面我们来看一个简单的例子:

# add a flag variable
break_out_flag = False
for i in range(5):
    for j in range(5):
        if j == 2 and i == 0:
            break_out_flag = True
            break
    if break_out_flag:
        break

如上所示, break_out_flag 变量是一个很好的信使messenger,可以告诉程序何时应该跳出外循环break out of the outer loop。

虽然效果不错,但我们的代码有点不整齐,因为我们添加了一个新变量variable来解决这个简单的问题。这并不是绝对必要的。

让我们来看看其他选择。

2. 抛出异常 Raise an Exception

如果我们不能按预期使用 break 关键字keyword。为什么不换一种方式来实现操作呢?在 Python 异常处理技术exception handling techniques 的帮助下,我们可以跳出嵌套循环,如下所示:

# raise an exception
try:
    for i in range(5):
        for j in range(5):
            if j == 2 and i == 0:
                raise StopIteration
except StopIteration:
    pass

正如上述程序所示,我们可以将 “中断break” 视为 “异常exception”,并将其抛出throw嵌套循环nested loops。

3. 再次检查相同条件 Check the Same Condition Again

由于一个条件condition会导致中断breaking,因此在每个循环中检查相同的条件condition也是一个可行的解决方案feasible solution。比如下面的例子:

# check the same condition again
for i in range(5):
    for j in range(5):
        if j == 2 and i == 0:
            break
    if j == 2 and i == 0:
        break

上述方法可行,但不是个好主意。至少效率不高。因为多次检查同一件事会浪费很多时间。

4. 使用 For-Else 语法 Use the For-Else Syntax

Python 有一种特殊的语法special syntax:“for-else”。它并不流行not popular,甚至有人从来不知道它。因为每个人的习惯都是在 "if "后面使用 “else”。

然而,当涉及到跳出嵌套循环时。这种非常规的语法可以提供帮助。

# use the for-else syntax
for i in range(5):
    for j in range(5):
        if j == 2 and i == 0:
            break
    else:  # only execute when it's no break in the inner loop
        continue
    break

上面的代码利用了 “for - else” 技术,因为 else 语句下的代码只有在内层inner loop循环完成且没有任何中断any breaking的情况下才会执行。

如果你还不熟悉 “for-else” 语法,请看看下面的代码。这是 “for-else” 示例的 “翻译”,即等效代码。

# the same as for-else syntax
for i in range(5):
    for j in range(5):
        if j == 2 and i == 0:
            break
    if not (j == 2 and i == 0):
        continue
    break 

总之,这种方法是可行的,但我们必须熟悉奇怪的 “if-else” 语法syntax。

5. 将其放入函数中 Put It Into a Function

如果我们将嵌套循环nested loops放入一个函数function中,破解问题就变得简单了。因为我们可以使用 return 关键字keyword,而不是 break

# make it as a function
def check_sth():
    for i in range(5):
        for j in range(5):
            if j == 2 and i == 0:
                return
check_sth() # Run the function when needed

如上所示,这种解决方案solution看起来更优雅more elegant。没有标志变量no flags variables,没有 “try-except” 或 “for-else” 语法syntax,也没有不必要的条件检查condition checking。

此外,“将谓词循环转化为谓词函数Turn Predicate Loops into Predicate Functions” 是 LLVM 编译器基础架构团队推出的一种良好的编码实践。

函数Functions在 Python 中非常灵活flexible。我们可以很容易地定义嵌套函数nested functions或闭包closures。因此,如果嵌套循环nested loops只在另一个函数function中使用一次,我们只需在外部函数outer function中定义即可:

def out_func():
    # do something
    def check_sth():
        for i in range(5):
            for j in range(5):
                if j == 2 and i == 0:
                    return
    # do something
    check_sth()  # Run the function when needed
    # do something

然而,仅为两个 for 循环定义嵌套函数似乎也不太优雅。

最终想法: 避免嵌套循环 Avoid Nested Loops

如果没有优雅的解决方案来跳出嵌套循环nested loops,为什么不避免编写嵌套循环呢?如果可能的话,我们会巧妙地将困难的问题变成更简单的问题。

通过使用一些辅助函数helper functions,我们确实可以避免嵌套循环avoid nested loops:

# Avoid nested loops
import itertools

for i, j in itertools.product(range(5), range(5)):
    if j == 2 and i == 0:
        break

如上所示,在 itertools.product 函数的帮助下,我们前面的示例可以避免嵌套循环。 product 函数会根据输入的可迭代对象iterables 生成笛卡尔积Cartesian product。

遗憾的是,这种方法无法避免所有嵌套循环nested loops。例如,如果我们需要在循环中处理无限的数据流,这种方法就无能为力。

注意:在 product() 运行之前,它会完全消耗输入的可迭代对象iterables,在内存中保留数值池以生成乘积。因此,它只适用于有限的输入。

但是,避免嵌套循环avoid nested loops和提高程序的可读性improve readability仍然是个好主意。

Conclusion 结论

在 Python 中,我们至少有五种跳出嵌套循环break out of nested loops的可行方法。它们都不如 PHP 的方法优雅,但至少我们可以实现这一操作。幸运的是,如果我们能借助 itertools.product 函数将嵌套循环nested loops转换为更简单的循环simpler loop,我们就不必使用嵌套循环nested loops了。

文章来源:https://blog.csdn.net/JENREY/article/details/135298495
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。