Python中zip(*[iter(s)]*n)是如何工作的?
s = [1,2,3,4,5,6,7,8,9]
n = 3
list(zip(*[iter(s)]*n)) # returns [(1,2,3),(4,5,6),(7,8,9)]
这个 zip(*[iter(s)]*n)
是怎么工作的?如果用更详细的代码来写,会是什么样子呢?
这是一个用于 将列表分割成相同大小块的技巧 - 可以查看那个问题,了解这个问题的整体情况。
9 个回答
35
我觉得在所有的回答中,有一点被忽略了(对那些熟悉迭代器的人来说可能很明显,但对其他人来说就不那么明显了)-
因为我们使用的是同一个迭代器,所以它会被消耗掉,剩下的元素会被zip函数使用。所以如果我们直接用列表,而不是用迭代器的话,比如:
l = range(9)
zip(*([l]*3)) # note: not an iter here, the lists are not emptied as we iterate
# output
[(0, 0, 0), (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6), (7, 7, 7), (8, 8, 8)]
使用迭代器时,它会逐个取出值,只保留剩下的可用值,所以对于zip来说,一旦0被取走了,1就可以用了,然后是2,依此类推。这是一个非常微妙的点,但真的很聪明!!!
53
其他很棒的回答和评论很好地解释了参数解包和zip()的作用。
正如Ignacio和ujukatzel所说,你把三个指向同一个迭代器的引用传给zip()
,然后zip()
会从每个引用中按顺序生成包含三个整数的元组:
1,2,3,4,5,6,7,8,9 1,2,3,4,5,6,7,8,9 1,2,3,4,5,6,7,8,9
^ ^ ^
^ ^ ^
^ ^ ^
而且因为你想要一个更详细的代码示例:
chunk_size = 3
L = [1,2,3,4,5,6,7,8,9]
# iterate over L in steps of 3
for start in range(0,len(L),chunk_size): # xrange() in 2.x; range() in 3.x
end = start + chunk_size
print L[start:end] # three-item chunks
根据start
和end
的值:
[0:3) #[1,2,3]
[3:6) #[4,5,6]
[6:9) #[7,8,9]
顺便说一下,你也可以用map()
来得到相同的结果,只需把初始参数设为None
:
>>> map(None,*[iter(s)]*3)
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
想了解更多关于zip()
和map()
的信息,可以查看这个链接:http://muffinresearch.co.uk/archives/2007/10/16/python-transposing-lists-with-map-and-zip/