理解zip函数
大家讨论的都是 Python 3.1.2 版本;你可以查看 Python 文档 来了解我问题的来源。
我知道 zip
是干什么的,但我不明白为什么它可以这样实现:
def zip(*iterables):
# zip('ABCD', 'xy') --> Ax By
iterables = map(iter, iterables)
while iterables:
yield tuple(map(next, iterables))
假设我调用 zip(c1, c2, c3)
。如果我理解得没错,最开始的 iterables
是一个包含 (c1, c2, c3) 的元组。
这行代码 iterables = map(iter, iterables)
把它转换成一个迭代器,这个迭代器如果被遍历的话,会依次返回 iter(c1)
、iter(c2)
和 iter(c3)
。
在循环内部,map(next, iterables)
是一个迭代器,如果遍历它,会返回 next(iter(c1))
、next(iter(c2))
和 next(iter(c3))
。然后 tuple
这个调用会把它转换成 (next(iter(c1)), next(iter(c2)), next(iter(c3))
,而且在第一次调用的时候就把它的参数(iterables
)用完了。至于我能理解的,我不明白为什么 while
循环还能继续,因为它是检查 iterables
;如果它继续的话,为什么 tuple
的调用不会返回一个空元组(因为迭代器已经用完了)。
我肯定是漏掉了什么很简单的东西……
2 个回答
看起来这段代码是为python-2.x版本写的。在python 3.x中,它甚至都无法正常运行。
在python-2.x中,map
会返回一个迭代器的列表,当你调用next
时,它会返回迭代器中的一个元素,这些元素会组合成一个元组。所以,假设有
>>> zip('ABCD', 'xy')
iterables是一个包含两个迭代器的列表,在while循环的每次迭代中,都会消耗迭代器中的第一个剩余元素(比如''A'
和'x'
等),并将其作为元组的一个元素返回。然后在最后一个元素被返回后(在第三次迭代时),会抛出StopIteration
,这会停止生成器。while iterables
始终保持为True
。
看起来这是文档中的一个错误。这个“等效”的代码在python2中可以正常运行,但在python3中却会陷入无限循环。
而且最新版本的文档也有同样的问题:http://docs.python.org/release/3.1.2/library/functions.html
看起来是变更61361导致了这个问题,因为它在没有确认这些改动对python3是否正确的情况下,直接合并了python 2.6的改动。
目前在主文档集中似乎没有这个问题,但你可能还是应该在http://bugs.python.org/上报告一下这个错误。