【问题标题】:Applying the list function to nested generators in itertools.groupby将列表函数应用于 itertools.groupby 中的嵌套生成器
【发布时间】:2017-05-05 21:34:34
【问题描述】:

list 函数在应用于嵌套生成器时表现如何?在下面的代码 sn-p 中,我发现这种行为相当令人费解:似乎list 消耗了大多数嵌套生成器,除了最后一个仍然保留一个元素的生成器:

>>> from itertools import groupby
>>> xs = [1, 2, 2, 3, 3]
>>> for k, g in list(groupby(xs)):
...     print(k, list(g))
1 []
2 []
3 [3]

【问题讨论】:

    标签: python python-3.x iterator generator


    【解决方案1】:

    不,对 list 的调用不会消耗嵌套的迭代器/生成器。

    这种行为是 itertools.groupby 特有的,并在文档中进行了描述:

    返回的组本身就是一个迭代器,共享底层 可与groupby() 迭代。因为源是共享的,当 groupby() 对象已高级,上一个组不再可见

    [强调我的]

    如果您查看文档中提供的与 itertools.groupby 等效的 Python 源代码,这将变得更容易解释:

    class groupby(object):
        def __init__(self, iterable, key=None):
            if key is None:
                key = lambda x: x
            self.keyfunc = key
    
            self.it = iter(iterable) # shared iterator
    
            self.tgtkey = self.currkey = self.currvalue = object()
    
        def __iter__(self):
            return self
    
        def next(self):
            while self.currkey == self.tgtkey:
                self.currvalue = next(self.it)    # Exit on StopIteration
                self.currkey = self.keyfunc(self.currvalue)
            self.tgtkey = self.currkey
            return (self.currkey, self._grouper(self.tgtkey))
    
        def _grouper(self, tgtkey):
            while self.currkey == tgtkey:
                yield self.currvalue
                self.currvalue = next(self.it)    # Exit on StopIteration
                self.currkey = self.keyfunc(self.currvalue)
    

    结果中显示的最后一个[3]self.currvalue(由_grouper 产生),它已经从groupby 对象的上一次调用中分配给下一个。

    为了保留每个组的结果,您应该将它们存储在一个列表中,而不是一次性使用 groupby 对象。

    【讨论】:

    • 非常感谢您的详尽回答!我应该更仔细地检查文档:-)
    猜你喜欢
    • 2021-11-03
    • 2021-07-12
    • 2020-06-06
    • 1970-01-01
    • 2012-07-07
    • 2011-02-03
    • 2010-12-09
    • 2011-08-07
    • 1970-01-01
    相关资源
    最近更新 更多