【问题标题】:Understanding buffering of tee了解 tee 的缓冲
【发布时间】:2014-06-01 08:19:32
【问题描述】:

在阅读了代码中涉及teethis answer 之后,我玩了一下,试图概括那里提出的解决方案。

任务是懒惰地“转置”一个列表。也就是说,列表[xrange(1, 4), xrange(4, 7), xrange(7, 10)](在 python 2.7 中)必须成为与[xrange(1, 10, 3), xrange(2, 10, 3), xrange(3, 10, 3)] 类似的东西。

我在这里复制那里提出的解决方案:

def transpose(iterable_of_three_tuples):
    teed = itertools.tee(iterable_of_three_tuples, 3)
    return (e[0] for e in teed[0]), (e[1] for e in teed[1]), (e[2] for e in teed[2])

我的概括是尝试做同样的事情,3 是一个参数。由于3 是输入生成器的长度,所以您无法猜测,必须将其添加为函数的参数。由于有些生成器可能很大甚至无限大,我也认为这个参数是一个限制,所以我们只取每个输入生成器的前 n 个元素。

这是我的代码:

def transpose(zipped, n):
    teed = tee(zipped, n)
    return [(e[i] for e in teed[i]) for i in xrange(n)]

这没有按预期工作,如下例所示:

>>> data = [xrange(1, 4), xrange(4, 7), xrange(7, 10)]
>>> x, y, z = transpose(data, 3)
>>> x.next()
3

(我预计是 1 个)。

我猜这与列表理解和名称泄漏中的生成器有关,或者是对 i 的惰性评估或类似的东西...您能说出我的代码有什么问题以及如何修复它吗?

【问题讨论】:

  • 您的问题与this question 中讨论的问题类似。该问题涉及 lambdas/functions,但生成器理解的范围规则是相同的。看看这个问题是否能帮助你理解发生了什么。
  • 我实际上很熟悉函数的范围问题;设置默认参数 (n=n) 是将名称转移到内部范围的解决方法。但是,我会在那里仔细阅读您的解决方案,并尝试将其应用于我自己的问题。
  • 你说得对:生成器闭包关闭名称,而不是值。

标签: python list-comprehension lazy-evaluation


【解决方案1】:

感谢@BrenBarn 的评论,这是一个(非常丑陋的)补丁修复。不过,欢迎您提出更好的建议。

def transpose(zipped, n):                          
    teed = tee(zipped, n)                            
    for i in xrange(n):
        gen = lambda teed, i=i: (e[i] for e in teed[i])
        yield gen(teed)

【讨论】:

    猜你喜欢
    • 2012-05-05
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 2018-05-06
    • 1970-01-01
    相关资源
    最近更新 更多