zip(* * n)在Python中如何工作?

s = [1,2,3,4,5,6,7,8,9] n = 3 zip(*[iter(s)]*n) # returns [(1,2,3),(4,5,6),(7,8,9)] 

zip(*[iter(s)]*n)工作? 如果使用更详细的代码编写,它会是什么样子?

iter()是一个序列的迭代器。 [x] * n产生一个包含nx的列表,即长度为n的列表,其中每个元素是x*arg一个序列解压缩到一个函数调用的参数中。 因此,你将相同的迭代器3次传递给zip() ,并且每次都从迭代器中取出一个项目。

 x = iter([1,2,3,4,5,6,7,8,9]) print zip(x, x, x) 

其他很好的答案和评论很好地解释了参数解包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 

遵循startend的值:

 [0:3) #[1,2,3] [3:6) #[4,5,6] [6:9) #[7,8,9] 

FWIW,你可以得到与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/

我认为在所有的答案中都错过了一件事(对那些熟悉迭代器的人可能是显而易见的),但是对其他人不那么明显 –

因为我们有相同的迭代器,所以它被占用,其余的元素被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)] 

使用迭代器,弹出的值,只有保持可用,所以对于拉链一次消耗1是可用的,然后是2等等。 一个非常微妙的东西,但相当聪明!

iter(s)为s返回一个迭代器。

[iter(s)]*n列出了n次与s相同的迭代器。

所以,在做zip(*[iter(s)]*n) ,它会依次从列表中的所有三个迭代器中提取一个项目。 由于所有的迭代器都是相同的对象,它只是将列表按n块分组。

就这样使用zip的一个建议。 它会截断你的列表,如果它的长度不是可以被整除的话。 要解决这个问题,你可以使用itertools.izip_longest,如果你可以接受填充值。 或者你可以使用这样的东西:

 def n_split(iterable, n): num_extra = len(iterable) % n zipped = zip(*[iter(iterable)] * n) return zipped if not num_extra else zipped + [iterable[-num_extra:], ] 

用法:

 for ints in n_split(range(1,12), 3): print ', '.join([str(i) for i in ints]) 

打印:

 1, 2, 3 4, 5, 6 7, 8, 9 10, 11