【问题标题】:itertools.cycle(iterable) vs while Trueitertools.cycle(iterable) vs while True
【发布时间】:2019-02-12 03:30:52
【问题描述】:

我最近被要求做这个任务(学校):

编写一个循环生成器,它以一个有限迭代器为参数,并在无限循环中生成迭代器

所以我做到了:

import itertools
def loop(l):
    for eleme‍‌​‍‌nt in itertools.cycle(l):
        yield element

我的一位同学做到了:

def loop(l):
    while True:
​‍         for element in l:
            yield element

我想知道两者之间的主要区别是什么,以及是否有更“pythonic”的方式来编写这样简单的东西。

【问题讨论】:

    标签: python python-3.x loops itertools


    【解决方案1】:

    你说得对,itertools.cycle 在这里对经典的 while True 循环并不感兴趣。

    另一方面,它对无限生成器推导有很大帮助,在这种情况下,您无法创建无限循环,因为它只允许for、测试和函数调用。无限期生成列表平方值的示例:

    generator = (x*x for x in itertools.cycle(l))
    

    当然,您可以随时缩短当前代码:

    def loop(l):
        yield from itertools.cycle(l)
    

    甚至:

    loop = itertools.cycle
    

    【讨论】:

      【解决方案2】:

      在我看来,itertools.cycle 的目的是您根本不必自己编写它:)

      最pythonic的方式是简单地写loop = itertools.cycle

      如果您确实需要将其编写为学校作业的生成器,则第二种形式可能会执行得更快,因为第一种形式基本相同,但也有额外的开销来自重新生成来自 cycle 的值你的发电机。

      【讨论】:

        【解决方案3】:

        我想知道两者之间的主要区别是什么...

        主要区别在于这些代码 sn-ps 在行为上并不完全等效。使用cycle,您可以接受并重复一个可耗尽的迭代器,而while 循环则不能。

        >>> def gen():
        ...     yield 1
        ...     yield 2
        ...     
        >>> def loop_it(it):
        ...     for element in itertools.cycle(it):
        ...         yield element
        ...         
        >>> g = loop_it(gen())
        >>> next(g)
        1
        >>> next(g)
        2
        >>> next(g)
        1
        

        对比度:

        >>> def loop_while(it):
        ...     while True:
        ...         for element in it:
        ...             yield element
        ...             
        >>> g = loop_while(gen())
        >>> next(g)
        1
        >>> next(g)
        2
        >>> next(g)
        # ... hangs forever
        

        ...如果有更“pythonic”的方式来编写这样简单的东西

        我的建议是 while 循环,完全按照书面说明。如果您在学校任务中​​被要求编写生成器,那么使用 itertools 中的“早先准备好的”可能会不受欢迎。 while 循环也更加 Pythonic。 “itertoolsthonic”方法将直接使用循环,如下所示:

        items = itertools.cycle(l)
        # do something with `items`
        

        没有必要编写生成器函数的额外脚手架和从itertools.cycle 产生的 for 循环 - 因为循环已经是一个迭代器,你可以直接使用它。

        【讨论】:

        • 技术上,gen(或者更技术上,它的返回值)是一个iterator,而不是一个iterable
        • @chepner 我会说生成器函数的返回值是一个迭代器和一个可迭代对象。我什至会说 每个 迭代器都是可迭代的。
        • 嗯,使用一些库没有问题,我们是在去年,但我们还没有python模块。所以使用库不是问题。但是我们的老师打了很多代码打高尔夫球:)
        猜你喜欢
        • 2016-08-11
        • 2015-02-15
        • 2015-07-09
        • 1970-01-01
        • 2013-03-02
        • 1970-01-01
        • 1970-01-01
        • 2011-07-11
        • 2020-10-30
        相关资源
        最近更新 更多