python - itertools 中的 izip_longest : what's going on here?

标签 python python-itertools

我正在努力理解下面的代码是如何工作的。来自http://docs.python.org/library/itertools.html#itertools.izip_longest , 并且是 izip_longest 迭代器的纯 python 等价物。我对 sentinel 函数特别迷惑,它是如何工作的?

def izip_longest(*args, **kwds):
    # izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
    fillvalue = kwds.get('fillvalue')
    def sentinel(counter = ([fillvalue]*(len(args)-1)).pop):
        yield counter()         # yields the fillvalue, or raises IndexError
    fillers = repeat(fillvalue)
    iters = [chain(it, sentinel(), fillers) for it in args]
    try:
        for tup in izip(*iters):
            yield tup
    except IndexError:
        pass

最佳答案

好的,我们可以做到这一点。关于哨兵。表达式 ([fillvalue]*(len(args)-1)) 创建一个列表,其中包含 args 中每个可迭代对象的一个​​填充值减一。因此,对于上面的示例 ['-']counter 然后被分配 pop - 该列表的功能。 sentinel 本身是一个 generator在每次迭代中从该列表中弹出一项。您可以对 sentinel 返回的每个迭代器进行恰好一次迭代,它总是会产生 fillvaluesentinel 返回的所有迭代器产生的项目总数是 len(args) - 1(感谢 Sven Marnach 澄清这一点,我误解了)。

现在看看这个:

iters = [chain(it, sentinel(), fillers) for it in args]

这就是诀窍。 iters 是一个列表,其中包含 args 中每个可迭代对象的迭代器。这些迭代器中的每一个都执行以下操作:

  1. args 中迭代相应的 iterable 中的所有项目。
  2. 遍历 sentinel 一次,产生 fillvalue
  3. 永远重复fillvalue

现在,如前所述,在它抛出 IndexError 之前,我们只能将所有哨兵一起迭代 len(args)-1 次。这很好,因为其中一个迭代器是最长的。因此,当我们到达引发 IndexError 的地步时,这意味着我们已经完成了对 args 中最长可迭代对象的迭代。

不客气。

P.S.:我希望这是可以理解的。

关于python - itertools 中的 izip_longest : what's going on here?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5298705/

相关文章:

python - 在 pytest 参数化中标记输入

python - django rest 框架 - 使用 View 集

python - 从django数据库中检索数据并显示在表中

Python - 生成具有特定模式的特定排列列表(添加到 itertools)

python - 自定义迭代器和 itertools.tee 问题

python smtplib 没有看到服务器发布的 starttls?

java - Python 中有标准的通用 URI 处理程序吗?

python - 从列表中创建组合,如果分隔符的子字符串位于列表项的 1 个以上子元素中,则删除组合

python - 如何计算二维数组元素之间差异的所有组合?

python - Python的itertools.count怎么可能不增加?