如何使用izip_longest来理解代码列表?

时间:2015-03-04 05:36:56

标签: python list iterator itertools

What is the most “pythonic” way to iterate over a list in chunks?中的最佳答案,使用 izip_longest 功能来列表列表。但我无法理解。

def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return izip_longest(*args, fillvalue=fillvalue)

for item in grouper(range(10), 4):
    print list(item)

我运行上面的代码,然后创建了分块列表:

[1 ,2, 3, 4]
[5, 6, 7, 8]
[9, 10, None, None]

我试图一步一步地运行它:

In [1]: args = [iter(range(10))] * 4

In [2]: args
Out[2]: 
[<listiterator at 0x1ad7610>,
 <listiterator at 0x1ad7610>,
 <listiterator at 0x1ad7610>,
 <listiterator at 0x1ad7610>]

列表由同一个迭代器创建。我知道实现了 izip_longest 功能来生成列表对。如何通过izip_longest将迭代器转换为分块列表?感谢。

1 个答案:

答案 0 :(得分:6)

grouper函数只是使用自身的偏移版本来压缩原始的iterable。使用[iter(iterable)] * n创建一个列表,其中n引用同一个迭代器。这些不是独立的副本;它们都是对同一个对象的引用,所以推进它们都会提升它们。这是一个简单的例子:

>>> x = [1, 2, 3]
>>> a, b = [iter(x)] * 2
>>> next(a)
1
>>> next(b)
2

izip_longestzip一样,每次从每个迭代器获取一个元素。首先,它从args中的第一个迭代中获取第一个元素,这将是原始可迭代的第一个元素。但是当它抓住这个元素时,它会推进所有的迭代器,因为它们都是链接的。因此,当izip_longest从下一个迭代器获取一个元素时,它将从原始的iterable中获取第二个元素。它继续这样下去;每当它从一个迭代器中获取一个元素时,它就会前进所有这些元素,这样它从下一个迭代器中获取的项将成为原始迭代中的下一个项。