【发布时间】:2014-06-01 08:19:32
【问题描述】:
在阅读了代码中涉及tee 的this 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