itertools“grouper”函数是如何工作的?

2024-05-23 08:51:06 发布

您现在位置:Python中文网/ 问答频道 /正文

从这里开始: https://docs.python.org/3/library/itertools.html#itertools-recipes

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

我理解zip_longest调用。但我不明白:

^{pr2}$

如果稍后要将iterable传递到izip_longest中,何必再费心将iterable包装成iter()?我不能这样做:

args = [iterable] * n

但似乎没有iter(),它只会重复相同的迭代器n次。但是把这个放在iter()中会如何改变它的行为呢?在


Tags: httpsorgdocslongestdefhtmllibraryargs
1条回答
网友
1楼 · 发布于 2024-05-23 08:51:06

这个分组利用了迭代器的单次传递特性(而不仅仅是iterable,它可能会多次迭代,并且在非iterator iterable上使用iter应该返回一个新的独立迭代器。相反,对迭代器调用iter将返回迭代器本身。在

因此,下面是一个只接受两个参数的zip函数的简单实现:

In [1]: def myzip(x, y):
   ...:     itx, ity = iter(x), iter(y)
   ...:     while True:
   ...:         try:
   ...:             a, b = next(itx), next(ity)
   ...:         except StopIteration:
   ...:             return
   ...:         yield a, b
   ...:

In [2]: list(zip('abcd','efgh'))
Out[2]: [('a', 'e'), ('b', 'f'), ('c', 'g'), ('d', 'h')]

In [3]: list(myzip('abcd','efgh'))
Out[3]: [('a', 'e'), ('b', 'f'), ('c', 'g'), ('d', 'h')]

这就是内置的zip的工作原理。现在,如果我们用一个列表作为iterable来执行上面的操作呢?在

^{pr2}$

但是,如果iterable是一个迭代器

In [25]: iterable = iter(mylist)

In [26]: itx, ity = iter(iterable), iter(iterable)

In [27]: itx is ity
Out[27]: True

In [28]: next(itx), next(ity)
Out[28]: (1, 2)

In [29]: next(itx), next(ity)
Out[29]: (3, 4)

In [30]: next(itx), next(ity)
                                     -
StopIteration                             Traceback (most recent call last)
<ipython-input-30-b6cbb26d280f> in <module>()
  > 1 next(itx), next(ity)

StopIteration:

最后,请注意,序列上的repition从不复制序列的元素,因此[iter(x)]*n将返回一个列表,其中包含对同一迭代器的n个引用,因此:

In [32]: args = [iter(mylist)]*3

In [33]: args
Out[33]:
[<list_iterator at 0x1040c9320>,
 <list_iterator at 0x1040c9320>,
 <list_iterator at 0x1040c9320>]

注意,它们是相同的list_iterator对象。。。在

相关问题 更多 >

    热门问题