【问题标题】:How to use a bundling/packetizing generator in Python?如何在 Python 中使用捆绑/打包生成器?
【发布时间】:2011-04-01 20:35:26
【问题描述】:

为了分摊函数调用开销,我更改了我的生成器,以便它生成一个包含几个值的固定长度列表,而不是一次生成一个值。生成器,就像它最初的样子,从一个包含几个腌制对象的文件中取消腌制一个对象,并产生它。然后在消耗生成器的 for 循环中处理这些。事实证明,这种方法比将对象处理代码放在手动展开循环中要慢得多,该循环一次解开文件中的几个连续项目。我正在尝试妥协。我修改后的生成器一次生成一个固定长度的腌制对象列表。我正在寻找一种 Python 风格的方法来在消费者端解压未腌制的对象包。

有没有办法在没有额外嵌套循环的情况下解构这些数据包?我错误地认为* 操作员会这样做:

for x in *packetizing_generator(): f(x)

嵌套循环当然可以,但我想知道是否有更短更优雅的方式。

【问题讨论】:

    标签: python generator


    【解决方案1】:

    我想这就是你在说的,如果我没有走在正确的轨道上,请告诉我。

    for a, b, c in your_generator:
        # do stuff
    

    假设 your_generator 产生的结果恰好是 3 个项目的序列。

    您可以使用以下方法构造一个生成器,该生成器一次准确地产生n 项,以在您的for 循环中使用:

    itertools.izip_longest(*[your_generator]*n)
    

    如果您的生成器一次不产生单个项目,并且您想更改它产生的项目数量,请使用以下命令:

    itertools.izip_longest(*[itertools.chain(*your_generator)]*n)
    

    这是一个例子:

    >>> from itertools import izip_longest, chain, combinations
    >>> for a, b, c, d in izip_longest(*[chain(*combinations(range(4), 2))]*4):
    ...     print a, b, c, d
    ... 
    0 1 0 2
    0 3 1 2
    1 3 2 3
    

    这需要一个最初一次产生两个项目的生成器,而是一次产生四个元素。

    【讨论】:

    • 那么需要给生成器一个yield length参数吗?您绝对应该能够以始终生成特定数量的项目的方式编写生成器。
    • 是的。生成器已编写完成。在消费者方面,我有一个嵌套循环。想知道是否有解构该数据包的 Pythonic 方式
    • 我认为嵌套循环可能是要走的路,但使用chain.from_iterable(your_generator)而不是chain(*your_generator)可能会获得更好的性能,使用*会强制整个生成器消耗,这是不必要的。
    • 感谢您的回答,这是先前评论的错字更正版本。嵌套的 for 循环结果是最快的。但很高兴知道“*”操作仅在函数调用的上下文中有效。所以它有点令人失望,因为它的函数调用是我希望避免的,在 *my_generator() 中使用 for x 之类的东西:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 1970-01-01
    • 2013-05-03
    • 2021-10-19
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多