【问题标题】:Why are there no control structures for python FOR loop?为什么python FOR循环没有控制结构?
【发布时间】:2013-11-19 00:03:14
【问题描述】:

在 Java 中,我们可以有这样的 FOR 循环

for (i = 0; i < 10; i += 1) {

}

然而这在 Python 中是不可能的; FOR 只能在“foreach”的意义上使用,循环遍历一个可迭代对象中的每个元素。

为什么在 Python 中遗漏了 FOR 循环的控制结构?

【问题讨论】:

  • 你可以用类似xrange的东西来完成同样的事情

标签: python loops for-loop


【解决方案1】:

The Zen of Python 说“应该有一种——最好只有一种——明显的方法。” Python 已经有这种方法了:

for i in xrange(10):
    pass

如果您想明确所有部分,您也可以这样做:

for i in xrange(0, 10, 1):
    pass

由于它已经有一个“明显”的方式来做,添加另一种方式将是 un-zen。 (那会是“nez”吗?)

(注意:在 Python 3 中,使用 range 而不是 xrange。)

C 风格的 for 循环具有更大的灵活性,但最终您可以使用 Python 的 while(或 C 的 while)编写等效循环,这不仅涉及“一种明显的方式”原则,还有“简单胜于复杂”等。当然,这完全是品味问题——在这种情况下,是 Guido van Rossum 的品味。

【讨论】:

  • cython 足够聪明,可以将这些循环特殊化为 c 风格的 for 循环,而无需 xrange 的开销。如果pypy 也能认出它,我不会感到惊讶。
【解决方案2】:

由于这是可以追溯到 Python 0.x 的迷雾中的问题之一(事实上,很可能是它的前身 ABC),唯一能真正回答的人是 Guido,而且只有在他记得的情况下。您可以尝试让他在他的 History of Python 博客上写一篇文章。

但是,这有一些很好的理由。

首先,只有for 的一种形式而不是两种不同的形式使语言更小——更易于人类学习和阅读,更易于计算机解析。

没有“foreach”风格的for 循环会导致很多错误,并使很多简单的代码更加冗长。

没有 C 风格的 for 循环会使一些已经非常复杂的 for 循环变得稍微复杂一些,因为它们强制它们成为 while 循环。它不会影响像你这样的简单循环,可以写成“foreach”循环,比如for i in range(10):——更简洁,更易读,更难出错。*

这样看,选择是显而易见的。


* 事实上,即使是复杂 循环也可以通过迭代器转换为foreach 循环。有时这是个好主意。例如,for (int i=2; i=next_prime(i); i&lt;1000000) 真的比for i in takewhile(lambda i: i&lt;1000000, generate_primes()): 好吗?有一个原因,C++ 逐渐添加了使后者成为可能的功能,以避免您在使用前者时容易犯的错误……

【讨论】:

    【解决方案3】:

    一般来说,迭代元素的性能更好。你可以得到相同的结果:

    for i in xrange(0, 20):
        pass
    

    你应该明确地阅读 python 的 zed: http://www.python.org/dev/peps/pep-0020/

    【讨论】:

      【解决方案4】:

      因为它只是一个while循环的语法糖

      i = 0
      while i < 10:
          # stuff
          i += 1
      

      如果您从未在 C 风格的 for 循环中遇到过一个错误,请举手。是这样想的。

      【讨论】:

      • 嗯,foreach 循环只是a while loop 的语法糖,但它仍然值得拥有……
      • C 风格的 for 循环对于特定的 while 循环来说是 not 语法糖,因为如果你在 C 风格的 for 循环中 continue,那么继续代码i += 1 被执行。在while 循环中并非如此。在这种情况下,“明显”的解决方法是将i += 1 放在循环的开头,将i = 0 更改为i = -1 并将i &lt; 10 更改为i &lt; 9,但可能会出现一些混乱尝试为 :-) 编写完全等效的 C 风格
      • @SteveJessop,你是对的。我的回答过于简单了。您也不能轻松地处理在 while 表达式中进行赋值的循环。我将把它归结为我尝试防御性编程并尽可能避免曲折的 C 循环的习惯。
      • 如果我需要做任何太花哨的事情而无法翻译成明显的forwhilewhile True: … break …,我将花哨的位放入genexpr(或itertools 调用或... ) 然后它就变成了一个明显的for 循环,其中breakcontinue 的意思正是你想要的......
      • @abarnert,这是一个很好的做法,因为如果生成器很复杂,您可以对其进行单元测试。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多