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)]
Run Code Online (Sandbox Code Playgroud)
zip(*[iter(s)]*n)
工作怎么样?如果用更详细的代码编写它会是什么样子?
Ign*_*ams 98
iter()
是序列上的迭代器.[x] * n
生成一个包含n
数量的列表x
,即n
每个元素所在的长度列表x
.*arg
将序列解包为函数调用的参数.因此,您将相同的迭代器传递3次zip()
,并且每次都从迭代器中提取一个项目.
x = iter([1,2,3,4,5,6,7,8,9])
print zip(x, x, x)
Run Code Online (Sandbox Code Playgroud)
ber*_*nie 43
其他很好的答案和评论很好地解释了参数解包和zip()的作用.
正如Ignacio和ujukatzel所说,你传递给zip()
同一个迭代器的三个引用,并按zip()
顺序从每个引用到迭代器生成3个元组的整数:
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
^ ^ ^
^ ^ ^
^ ^ ^
Run Code Online (Sandbox Code Playgroud)
因为你要求更详细的代码示例:
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
Run Code Online (Sandbox Code Playgroud)
下面的值start
和end
:
[0:3) #[1,2,3]
[3:6) #[4,5,6]
[6:9) #[7,8,9]
Run Code Online (Sandbox Code Playgroud)
FWIW,您可以map()
使用以下初始参数获得相同的结果None
:
>>> map(None,*[iter(s)]*3)
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
Run Code Online (Sandbox Code Playgroud)
欲了解更多信息zip()
,请访问map()
:http: //muffinresearch.co.uk/archives/2007/10/16/python-transposing-lists-with-map-and-zip/
gab*_*jit 29
我认为在所有答案中都缺少一件事(对熟悉迭代器的人来说可能很明显)但对其他人来说并不那么明显 -
由于我们有相同的迭代器,因此它会被消耗掉并且zip使用其余的元素.所以,如果我们只使用列表而不是iter,例如.
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)]
Run Code Online (Sandbox Code Playgroud)
使用迭代器,弹出值并仅保持剩余可用,因此对于zip,一旦消耗0,则可用1,然后是2,依此类推.一个非常微妙的事情,但相当聪明!
iter(s)
返回s的迭代器.
[iter(s)]*n
为s创建n次相同迭代器的列表.
因此,在执行操作时zip(*[iter(s)]*n)
,它会按顺序从列表中的所有三个迭代器中提取项目.由于所有迭代器都是同一个对象,因此它只是按照块的形式对列表进行分组n
.
展开“聪明”的层层,你可能会发现这个等效的拼写更容易理解:
x = iter(s)
for a, b, c in zip(*([x] * n)):
print(a, b, c)
Run Code Online (Sandbox Code Playgroud)
反过来,这相当于更不聪明的:
x = iter(accounts_iter)
for a, b, c in zip(x, x, x):
print(a, b, c)
Run Code Online (Sandbox Code Playgroud)
现在事情应该开始变得清楚了。只有一个迭代器对象,x
。在每次迭代中,zip()
,在幕后调用next(x)
3 次,每个迭代器对象传递给它一次。但每次都是相同的迭代器对象。因此,它传递前 3 个next(x)
结果,并让共享迭代器对象等待接下来传递其第四个结果。起泡沫,冲洗,重复。
顺便说一句,我怀疑你*([iter(x)]*n)
的头脑解析不正确。首先发生尾随*n
,然后将前缀*
应用于*n
创建的 n 元素列表。f(*iterable)
是一种f()
使用可变数量的参数进行调用的快捷方式,每个对象iterable
传递一个参数。
用这种方式使用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:], ]
Run Code Online (Sandbox Code Playgroud)
用法:
for ints in n_split(range(1,12), 3):
print ', '.join([str(i) for i in ints])
Run Code Online (Sandbox Code Playgroud)
打印:
1, 2, 3
4, 5, 6
7, 8, 9
10, 11
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
26462 次 |
最近记录: |