首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python ` `for i in iter` vs‘`while;i=next(Iter)’

python ` `for i in iter` vs‘`while;i=next(Iter)’
EN

Stack Overflow用户
提问于 2015-01-03 23:46:00
回答 3查看 1.7K关注 0票数 3

据我理解,这两种方法都适用于生成器中的每个项目:

  • i成为我们的运营商目标
  • my_iter成为我们的发电机
  • 让可调用的do_something_with返回None

While循环+ StopIteratioon

代码语言:javascript
复制
try:
    while True:
        i = next(my_iter)
        do_something_with(i)
except StopIteration:
    pass

用于循环/列表理解

代码语言:javascript
复制
for i in my_iter:
    do_something_with(i)

代码语言:javascript
复制
[do_something_with(i) for i in my_iter]

次要编辑:按照@kojiro的建议,print(i)替换为do_something_with(i),用解释器机制消除用例的歧义。

据我所知,这两种方法都适用于对生成器进行迭代,是否有理由选择一种而另一种呢?

现在for循环在我看来更好。由于:线/杂乱和可读性一般较少,加上单个缩进。

如果您想轻松地打开特定异常的循环,那么我真的认为while方法是有利的。

EN

回答 3

Stack Overflow用户

发布于 2015-01-04 00:05:24

第三种选择与前两种截然不同。第三个示例创建一个列表,每个列表用于print(i)的返回值,它恰好是None,所以不是一个非常有趣的列表。

前两者在语义上是相似的。这里有一个细微的技术差异;如果my_iter实际上不是迭代器(例如,有一个__next__()方法),那么There循环就不能工作;例如,如果它是一个list。for循环除迭代器外,还适用于所有可迭代性(有一个__iter__()方法)。

因此,正确的版本是:

代码语言:javascript
复制
my_iter = iter(my_iterable)
try:
    while True:
        i = next(my_iter)
        print(i)
except StopIteration:
    pass

现在,除了可读性的原因之外,实际上还有一个技术原因,您应该更喜欢for循环;对于在紧的内部循环中执行的字节码的数量,您要付出一定的代价(在CPython中)。让我们比较一下:

代码语言:javascript
复制
In [1]: def forloop(my_iter):
   ...:     for i in my_iter:
   ...:         print(i)
   ...:         

In [57]: dis.dis(forloop)
  2           0 SETUP_LOOP              24 (to 27)
              3 LOAD_FAST                0 (my_iter)
              6 GET_ITER
        >>    7 FOR_ITER                16 (to 26)
             10 STORE_FAST               1 (i)

  3          13 LOAD_GLOBAL              0 (print)
             16 LOAD_FAST                1 (i)
             19 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             22 POP_TOP
             23 JUMP_ABSOLUTE            7
        >>   26 POP_BLOCK
        >>   27 LOAD_CONST               0 (None)
             30 RETURN_VALUE

内部循环中调用的7个字节码vs:

代码语言:javascript
复制
In [55]: def whileloop(my_iterable):
   ....:     my_iter = iter(my_iterable)
   ....:     try:
   ....:         while True:
   ....:             i = next(my_iter)
   ....:             print(i)
   ....:     except StopIteration:
   ....:         pass
   ....:     

In [56]: dis.dis(whileloop)
  2           0 LOAD_GLOBAL              0 (iter)
              3 LOAD_FAST                0 (my_iterable)
              6 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
              9 STORE_FAST               1 (my_iter)

  3          12 SETUP_EXCEPT            32 (to 47)

  4          15 SETUP_LOOP              25 (to 43)

  5     >>   18 LOAD_GLOBAL              1 (next)
             21 LOAD_FAST                1 (my_iter)
             24 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             27 STORE_FAST               2 (i)

  6          30 LOAD_GLOBAL              2 (print)
             33 LOAD_FAST                2 (i)
             36 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             39 POP_TOP
             40 JUMP_ABSOLUTE           18
        >>   43 POP_BLOCK
             44 JUMP_FORWARD            18 (to 65)

  7     >>   47 DUP_TOP
             48 LOAD_GLOBAL              3 (StopIteration)
             51 COMPARE_OP              10 (exception match)
             54 POP_JUMP_IF_FALSE       64
             57 POP_TOP
             58 POP_TOP
             59 POP_TOP

  8          60 POP_EXCEPT
             61 JUMP_FORWARD             1 (to 65)
        >>   64 END_FINALLY
        >>   65 LOAD_CONST               0 (None)
             68 RETURN_VALUE

内循环中的9位字节码。

不过,我们实际上可以做得更好。

代码语言:javascript
复制
In [58]: from collections import deque

In [59]: def deqloop(my_iter):
   ....:     deque(map(print, my_iter), 0)
   ....:     

In [61]: dis.dis(deqloop)
  2           0 LOAD_GLOBAL              0 (deque)
              3 LOAD_GLOBAL              1 (map)
              6 LOAD_GLOBAL              2 (print)
              9 LOAD_FAST                0 (my_iter)
             12 CALL_FUNCTION            2 (2 positional, 0 keyword pair)
             15 LOAD_CONST               1 (0)
             18 CALL_FUNCTION            2 (2 positional, 0 keyword pair)
             21 POP_TOP
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE

C中发生的一切,collections.dequemapprint都是内置的。(对于cpython)所以在本例中,没有为循环执行字节码。当迭代步骤是c函数时,这只是一个有用的优化(就像print的情况一样)。否则,python函数调用的开销要大于JUMP_ABSOLUTE开销。

票数 5
EN

Stack Overflow用户

发布于 2015-01-04 00:00:28

for循环是最重要的一环。请注意,您可以区分for循环和while循环。

除非您需要结果列表,否则不要使用列表理解,否则您将不必要地存储所有元素。示例列表理解只适用于Python 3中的print函数,而不适用于Python 2中的print语句。

票数 3
EN

Stack Overflow用户

发布于 2015-01-04 00:08:12

我同意你的观点,for循环是优越的。正如你所提到的,它不那么杂乱,而且更容易读懂。程序员喜欢尽可能地保持简单,而for循环就是这样做的。对于那些可能还没有学过try/except的新手Python程序员来说,这也更好。此外,正如Alasdair所提到的,您可以跳出for循环。此外,如果要使用列表,则while循环将运行一个错误,除非您首先在my_iter上使用iter()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27760818

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档