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

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

文章目录

  • [在 Python 中跳出嵌套循环的 5 种方法(5 Ways To Break Out of Nested Loops in Python)](#在 Python 中跳出嵌套循环的 5 种方法(5 Ways To Break Out of Nested Loops in Python))
    • [1. 添加标志变量 Add a Flag Variable](#1. 添加标志变量 Add a Flag Variable)
    • [2. 抛出异常 Raise an Exception](#2. 抛出异常 Raise an Exception)
    • [3. 再次检查相同条件 Check the Same Condition Again](#3. 再次检查相同条件 Check the Same Condition Again)
    • [4. 使用 For-Else 语法 Use the For-Else Syntax](#4. 使用 For-Else 语法 Use the For-Else Syntax)
    • [5. 将其放入函数中 Put It Into a Function](#5. 将其放入函数中 Put It Into a Function)
    • [最终想法: 避免嵌套循环 Avoid Nested Loops](#最终想法: 避免嵌套循环 Avoid Nested Loops)
    • [Conclusion 结论](#Conclusion 结论)

我们都知道,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:

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。下面我们来看一个简单的例子:

python 复制代码
# 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 的帮助下,我们可以跳出嵌套循环,如下所示:

python 复制代码
# 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。比如下面的例子:

python 复制代码
# 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"。

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

python 复制代码
# 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" 示例的 "翻译",即等效代码。

python 复制代码
# 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

python 复制代码
# 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中定义即可:

python 复制代码
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:

python 复制代码
# 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了。

相关推荐
游客52039 分钟前
设计模式-结构型-装饰器模式
python·设计模式·装饰器模式
petunsecn40 分钟前
将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch(3 纯python的经济方案)
python·elasticsearch·microsoft·azure
测试杂货铺1 小时前
单元测试与unittest框架
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
yzx9910131 小时前
Python根据图片生成学生excel成绩表
python·mysql·excel
Channing Lewis2 小时前
Python 3.9及以上版本支持的新的字符串函数 str.removeprefix()
服务器·python
唐BiuBiu2 小时前
python如何解析word文件格式(.docx)
python·word
测试秃头怪3 小时前
银行测试:第三方支付平台业务流,功能/性能/安全测试方法
自动化测试·软件测试·python·功能测试·测试工具·测试用例·安全性测试
清弦墨客3 小时前
【蓝桥杯】43689.包子凑数
python·蓝桥杯·编程算法
jessie的垃圾桶3 小时前
点云目标检测训练数据预处理---平面拟合与坐标转换(python实现)
python·变换矩阵·open3d·点云平面拟合
如若1233 小时前
pip install tensorflow==1.12.2(python=3.5)
python·tensorflow·pip