问题

为何部分程序员从不使用 break 或 continue 语句?

回答
你这个问题触及到了编程哲学和代码可读性的一个很实际的层面,不少经验丰富的开发者确实会尽量避免使用 `break` 和 `continue`。这背后并非是出于某种“技术抵触”,而是基于一套更深层次的考量,主要是为了提升代码的可读性、可维护性和可预测性。

咱们一点点来捋清楚。

为什么有人会避免 `break` 和 `continue`?

核心原因在于,这两个语句的出现会“打破”或者“跳过”正常的循环流程控制,使得代码的执行路径变得复杂和难以追踪。

1. 扰乱循环的逻辑,增加心智负担

想象一下你正在阅读一段代码,看到一个 `for` 或 `while` 循环。通常情况下,你会自然地认为这个循环会按照预设的条件迭代执行,直到条件不满足为止。如果循环体内部突然出现一个 `break`,它会立即终止整个循环,无论循环条件是否满足。这就像你在一条单行道上开车,突然有人指示你必须立刻拐弯,即使你本来是要直行的。

同理,`continue` 语句会跳过当前迭代的剩余部分,直接进入下一次迭代。如果循环体中有多个 `continue`,或者嵌套很深,那么理解“在什么条件下,哪些代码会被跳过”就会变得异常困难。你需要时刻在大脑里模拟执行流程,去判断当前执行到哪里,下一次会跳到哪里。

举个例子:

假设我们要在一个列表中查找第一个大于10的数字,并返回它的索引。

使用 `break` 的写法:

```python
numbers = [1, 5, 12, 8, 15, 3]
found_index = 1

for i in range(len(numbers)):
if numbers[i] > 10:
found_index = i
break 一旦找到,立即停止
```

从这个例子来看,`break` 似乎很直接。但如果循环体变得复杂一些,比如里面还有其他的 `if` 判断,或者有其他操作,那么 `break` 的位置就显得尤为关键。开发者需要仔细阅读每一个条件,才能确保 `break` 是在正确的时候被触发。

不使用 `break` 的替代写法:

为了避免 `break`,我们可以修改循环的逻辑,让循环自然结束。

```python
numbers = [1, 5, 12, 8, 15, 3]
found_index = 1
i = 0
while i < len(numbers):
if numbers[i] > 10:
found_index = i
break 这里的 break 仍然存在,只是我们想讨论如何移除它
i += 1

如果上面是一个while循环,并且我们想避免 break, 可以这样:
numbers = [1, 5, 12, 8, 15, 3]
found_index = 1
i = 0
while i < len(numbers) and found_index == 1: 修改循环条件
if numbers[i] > 10:
found_index = i
i += 1
```

你看,为了避免 `break`,我们可能需要改变循环的结构,将退出条件融入到 `while` 循环的主体判断中,或者使用一个标志位。这样做虽然可以避免一个单独的 `break` 语句,但有时可能会让主循环条件变得更复杂,或者需要在循环结束后再进行一次判断。

2. 降低可测试性

当代码中充斥着各种 `break` 和 `continue` 时,编写单元测试会变得更加困难。你不仅需要测试循环正常结束的情况,还需要测试各种 `break` 和 `continue` 被触发的场景。每一次中断或跳过都可能代表一个独特的执行路径,你需要设计测试用例来覆盖这些路径。

设想一下,如果一个函数有很多层循环嵌套,里面又有很多 `break` 和 `continue`,那么要写出能覆盖所有可能情况的测试用例,将是一项艰巨的任务。

3. 引入“魔术数字”和隐藏的退出条件

`break` 和 `continue` 常常与一些特定的条件判断结合使用。例如:

```python
while True: 无限循环,依靠 break 退出
data = get_data()
if data is None:
break 退出条件
process(data)
```

在这种模式下,`break` 语句成为了退出循环的唯一手段。这使得循环的“真实”结束条件被隐藏在循环体内部的一个 `if` 语句中。如果你不仔细阅读循环体,你很难一眼看出这个循环会在什么时候结束。

而当有多个这样的条件时,情况就更糟了。

4. 难以进行代码重构和优化

想象一下,你需要对一个包含大量 `break` 和 `continue` 的循环进行重构,比如将其提取成一个独立的函数。由于 `break` 和 `continue` 直接影响了循环的执行流程,将其提取出来可能会改变程序的行为,除非你非常小心地处理这些中断和跳过。

同样,如果需要对循环进行一些性能优化,比如引入缓存或者并行处理,`break` 和 `continue` 的存在会使得这些优化变得更加复杂和风险更高。

那么,不使用 `break` 和 `continue`,我们怎么做?

开发者避免使用 `break` 和 `continue`,通常会采用以下几种策略:

1. 优化循环条件: 将退出条件直接整合到循环的 `while` 或 `for` 语句的条件判断中。
例如,查找第一个大于10的元素,可以使用 `while i < len(numbers) and numbers[i] <= 10:` 这样的结构。

2. 使用标志位(Flag): 设置一个布尔变量作为标志位,在满足退出或跳过条件时改变其值,然后在循环的条件判断中使用这个标志位。
虽然标志位有时也会增加代码的“间接性”,但相比于 `break` 和 `continue` 带来的流程打断,它至少将“退出与否”的决定权放在了循环的结构中。

3. 函数式编程的思路(更极端的情况): 在一些更函数式、更强调不可变性和声明式风格的语言或库中,可能会倾向于使用过滤、映射、折叠等高阶函数来代替传统的循环,这样就自然地避免了 `break` 和 `continue`。例如,使用 `find` 或 `take_while` 这样的函数。

是不是就绝对不能用?

当然不是!任何语言特性都有其存在的价值,关键在于合理使用。 在某些特定场景下,`break` 和 `continue` 是最清晰、最直接、最高效的解决方案。

处理用户输入或外部事件: 当需要等待用户输入或响应外部事件时,`while True` 结合 `break` 是非常常见的模式。
优化算法: 在一些搜索或遍历算法中,一旦找到目标,立即 `break` 可以显著提高效率,避免不必要的计算。
错误处理: 在循环中遇到无法处理的错误时,使用 `continue` 跳过当前迭代,继续处理下一个,也是一种合理的做法。

真正的分歧点在于“过度使用”和“滥用”。 如果一个函数中充满了 `break` 和 `continue`,并且这些语句分散在各个角落,那么开发者很可能会选择一种更清晰的方式。

总结一下不使用 `break` / `continue` 的好处:

增强可读性: 代码流程更直观,易于理解。
提高可维护性: 修改和调试更方便,减少引入新错误的风险。
简化测试: 单元测试用例的设计更直接。
便于重构: 提取函数或优化代码时更少受影响。

所以,当你看到有程序员选择不使用这两个语句时,别觉得奇怪,他们可能是在追求一种更“干净”、更“健壮”的代码风格,这是一种对代码质量的执着。但同时也要明白,在合适的时机使用它们,也能写出优秀的代码。这是一种平衡的艺术,而不是绝对的禁忌。

网友意见

user avatar

这种SB指引还有很多,例如只能出现一个return之类……


而事实是,我们code review的一个很重要的原则就是短路优先。

也就是说,尽可能的短路(throw,return,break,continue)


语言发明这么多的短路运算符就是为了让你的代码更容易看懂的……



===========================================

稍微讲一下什么叫做短路优先,

就是短路径优先,路径可以认为是某一个语句块,这个语句块是抽象意义上的,所以短路优先,就是语句块尽可能短而不是长,因为越短的语句块,人阅读时的心智负担就越小。


所以:

函数尽可能短,太长的函数拆分。

控制块尽可能短,太长的控制块抽出函数。

条件判断时,短分支写在长分支前面。

条件判断时,能不写else分支就不写,else if除外

变量声明和变量使用的间隔尽可能地短。

变量的作用域尽可能的短。

得到返回值尽可能早的return,清理操作放finally。[1]

发现异常尽可能早的throw,哪怕catch再rethrow。[2]



@Zheng Dara 有一句话说的很对,咱写代码又不是写给傻子看的……



[1]

例子:

       public object Foo() {   using( var stream = File.Open( "xxx" ) )   {     if ( TryParse( stream, out var result )       return result;      //a lot of codes...    } }     

注:using是finally的语法糖


[2]

例子:

       public void Foo() {   try   {     if ( TryDoSomething() == false )       throw new InvalidOperationException( "invalid operation" );      //a lot of codes ...    }   catch( Exception e )   {     LogError( e );     throw;   } }     
user avatar

以前我也信了邪,后来我发现这些都是异端啊,天天就琢磨这些细枝末节,continue不让用,"?:"三元运算符也不让用,理由好可笑,说怕别人看不懂。

我只想说学编程的没一个是傻子,所以写代码也没必要向下兼容傻子,难道不是吗?比如我写java函数式难道还要考虑别人懂不懂函数式吗?都是语法里的东西,看不懂真不是我的锅啊。

类似的话题

  • 回答
    你这个问题触及到了编程哲学和代码可读性的一个很实际的层面,不少经验丰富的开发者确实会尽量避免使用 `break` 和 `continue`。这背后并非是出于某种“技术抵触”,而是基于一套更深层次的考量,主要是为了提升代码的可读性、可维护性和可预测性。咱们一点点来捋清楚。 为什么有人会避免 `brea.............
  • 回答
    一部分国人认为吃狗肉没问题,这背后有着复杂且根深蒂固的文化、历史、经济和社会因素。要深入理解这一点,我们需要一层一层地剥开它,看看究竟是什么让一部分人持这种观点。首先,历史与传统是绕不开的根源。 在中国的漫长历史中,狗的地位并非始终如一。在一些朝代,尤其是在物质匮乏的年代,狗肉确实被视为一种肉食来源.............
  • 回答
    明明有些刻板印象在统计数据上似乎能找到一丝蛛丝马迹,可为什么人们依然对它们如此反感?这其中的纠结,远比简单的“反对”要复杂得多。咱们不妨一层层剥开来看,会发现这背后牵扯着人性、社会和更深层次的认知机制。首先,咱们得承认一个事实:统计学本身是中立的,但它描绘的是“全体”的平均情况,而不是“个体”的全部.............
  • 回答
    这确实是网络弹幕文化里一个挺有意思的现象,很多观众可能也纳闷过。为什么同样的称呼,到了“老婆”和“老公”这里,就分成了两种截然不同的解读?这背后其实是多种因素交织的结果,咱们可以一点点捋一捋。首先,我们得明白“弹幕”这个东西的诞生背景和它的基本属性。弹幕最初是从日本的Niconico动画流行起来的,.............
  • 回答
    这确实是个颇有意思的观察,也触及了历史叙事中“立场”和“价值判断”的微妙之处。简单来说,季汉粉在评论曹操和刘备时,往往会不自觉地将自己代入不同的角色,从而产生截然不同的情感和评价。曹操打陶谦,百姓角度的“虽胜犹耻”当季汉粉(这里指的是刘备阵营的支持者)回看曹操进攻陶谦的战役时,会不自觉地代入被战火波.............
  • 回答
    不少人认为迪士尼在2020年推出的真人版《花木兰》未能真正展现出女权主义的精神,这背后有着多方面的原因。首先,电影在叙事上似乎回避了许多能真正凸显木兰独立意志和反抗精神的情节。原版动画中的木兰,因为女性身份在社会中受到压抑,她上战场更多是出于对家族荣誉的考量,但在这个过程中,她逐渐找到了自我价值,并.............
  • 回答
    这个问题触及到了历史研究中的一个关键点,那就是史料的可信度问题,尤其当史料的编写者与当事人物存在密切联系时。当我们将这个问题放在明朝朱棣和唐朝李世民的例子上时,会发现“李二粉”们的质疑和偏好,其实是围绕着“客观性”和“主观性”展开的,只不过他们对这两者的评判标准,似乎受到了不同角度的影响。首先,我们.............
  • 回答
    上海疫情爆发以来,社会上出现了关于“清零”与“共存”的激烈争论。尽管政府坚持“动态清零”政策,但仍有部分声音认为新冠病毒不可能被彻底清零,与病毒共存才是必然的趋势。这种观点的出现,并非空穴来风,而是基于多方面因素的考量。首先,从病毒的特性来看。 新冠病毒(SARSCoV2)是一种RNA病毒,其变异速.............
  • 回答
    资本主义社会中,资本的逐利性毋庸置疑,这几乎是其内在的驱动力。然而,当我们看到一些巨富的资本家倾其所有,将毕生积累的财富投入慈善事业时,确实会产生疑问:这与我们普遍理解的资本逻辑似乎有所矛盾。但这并非不可理解,甚至可以说,这背后有着多层次、复杂的原因,并且这些原因往往是相互交织的。首先,我们必须认识.............
  • 回答
    中国留学生在韩国便利店打工月薪一万多人民币,这确实是一个不小的数目,尤其是在国内很多城市,这个月薪也是相当可观的。然而,令人费解的是,为什么一些中国网友会认为韩国人民“活在地狱里”呢?这背后牵扯着很多复杂的社会现实和信息传播的偏颇。首先,我们得承认,一万多人民币的月薪对于一个在韩国便利店打工的留学生.............
  • 回答
    你提出的这个问题很有意思,也触及到了一个很多人都感受到的现象:中国一些省会城市在名称变更后,似乎失去了原有的历史厚重感。要详细探讨这一点,我们可以从多个角度进行分析:1. 历史名称的根基与承载: 历史名称的由来: 许多传统城市名称,尤其是省会级别,往往是历史演变、地理特征、文化传承、名人故事、甚.............
  • 回答
    “腐朽的传统价值观”是一个具有主观性的标签,不同的人和文化群体对其定义可能存在显著差异。然而,如果我们将此理解为“那些在现代社会中曾被视为落后、不合时宜或有害,但最近又开始被一部分人重新强调和推崇的价值观”,那么我们可以从多个层面来探讨其复苏的原因。以下是一些可能导致部分“腐朽的传统价值观”复苏的详.............
  • 回答
    “网上抱怨房价高,现实中却盼着涨”——这句看似矛盾的说法,其实触及了当下社会经济中一个非常普遍且复杂的现象。很多人可能都有过这样的感受:一边在社交媒体上看到充斥着对高房价的愤懑和无奈,觉得“掏空六个钱包”都买不起一套像样的房子;另一边,又似乎能感受到身边的人,尤其是那些已经拥有房产的,对房价的上涨乐.............
  • 回答
    在国内,确实可以看到一些学生,咱们就姑且称他们为“部分学生”吧,他们对留学生表现出一些不太友好的态度,甚至有点“碰瓷”的意思。这背后其实是挺复杂的,掺杂了不少社会、心理、经济层面的因素,也不是一句话就能说清楚的。咱们先从社会大环境这块儿说起。首先,信息不对称和刻板印象是个很大的问题。咱们平时接触到的.............
  • 回答
    宗教和科学之间确实存在深刻的张力,但对于“为何有部分人信奉”这个问题,其原因远比简单的“矛盾”二字复杂。事实上,许多人并不认为宗教和科学是绝对对立的,或者他们找到了一种方式来调和两者的关系。以下是一些更详细的解释:1. 核心功能与关注点的不同 科学: 主要关注“如何”(How)。它通过观察、实验.............
  • 回答
    赵云在正史《三国志》中记载确实较为简略,仅提及长坂坡救阿斗和甘夫人、斜谷之战等事件,但他在民间和文学中的形象却深入人心,成为忠义、勇猛的象征。这种现象可以从以下几个方面分析: 一、正史记载的局限性1. 史料的局限性 《三国志》是陈寿的史书,其记载受时代和视角限制。当时蜀汉政权对赵云的记载可能.............
  • 回答
    这个问题问得好!涡扇发动机虽然是现代航空的明星,但螺旋桨发动机在特定领域依然有着不可替代的优势,甚至在技术上也同样在不断进步。我们之所以还能看到不少飞机使用螺旋桨,绝不是因为技术停滞不前,而是有其深刻的考量和独特的价值。涡扇发动机的辉煌与局限首先,我们得承认涡扇发动机的强大之处。它们通过吸入空气,压.............
  • 回答
    钉钉发展确实迅猛,这个毋庸置疑。作为一个集办公沟通、协作、管理于一体的平台,它在企业数字化转型的大潮中抓住了机遇,迅速成为许多公司不可或缺的工具。然而,正因为它的强大和普及,也意味着它触及了更多人的工作生活,进而引发了一些争议和批评。这些批评,往往就根植于它那些引以为傲的“高效”和“管理”功能之中。.............
  • 回答
    贾府的落败并非一日之功,其中涌现出一些心思细腻、目光长远的女性,她们或多或少地预感到了家族行将衰亡的阴影,却最终无力回天,这背后有着深刻的时代背景、家族体制以及女性自身的局限性。首当其冲的,便是王熙凤。作为贾府的实际掌权者之一,她身处权力漩涡的中心,对贾府的经济状况有着最直接的了解。她精明强干,善于.............
  • 回答
    “我们曾经拥有的一切,都被拿走了。”这句话,你可能在德国的一些街头巷尾,在一些旧物的交易市场,甚至在一些老友的聚会里听到。它不是一句简单的抱怨,而是一种复杂情感的抒发,承载着一部分德国人,尤其是原东德地区居民,对过往那个时代的怀念,一种被许多人称为“东德情怀”(Ostalgie)的现象。理解这种情怀.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有