itertools中的izip_longest:这是怎么回事? [英] izip_longest in itertools: what's going on here?

查看:71
本文介绍了itertools中的izip_longest:这是怎么回事?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力理解以下代码的工作方式.来自 http://docs.python.org/library/itertools.html#itertools .izip_longest ,与izip_longest迭代器的纯Python等效.我尤其对哨兵功能感到迷惑,它是如何工作的?

I'm struggeling to understand how the below code works. It's from http://docs.python.org/library/itertools.html#itertools.izip_longest, and is the pure-python equivalent of the izip_longest iterator. I'm especially mystified by the sentinel function, how does it work?

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本身是生成器,它会在每个列表中弹出一个项目迭代.您可以仅对sentinel返回的每个迭代器进行一次迭代,并且始终会生成fillvalue. sentinel返回的所有迭代器产生的项目总数为len(args) - 1(感谢Sven Marnach澄清了这一点,我误解了).

Ok, we can do this. About the sentinel. The expression ([fillvalue]*(len(args)-1)) creates a list that contains one fill value for each iterable in args, minus one. So, for the example above ['-']. counter is then assigned the pop-function of that list. sentinel itself is a generator that pops one item from that list on each iteration. You can iterate over each iterator returned by sentinel exactly once, and it will always yield fillvalue. The total number of items yielded by all iterators returned by sentinel is len(args) - 1 (thanks to Sven Marnach for clarifying that, I misunderstood it).

现在检查一下:

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

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

That is the trick. iters is a list that contains an iterator for each iterable in args. Each of these iterators does the following:

  1. 遍历args中对应的可迭代项中的所有项.
  2. 遍历哨兵一次,产生fillvalue.
  3. 对所有永恒重复fillvalue.
  1. Iterate over all items in the corresponding iterable from args.
  2. Iterate over sentinel once, yielding fillvalue.
  3. Repeat fillvalue for all eternity.

现在,如前所述,我们只能在抛出IndexError之前,将所有哨兵一起迭代len(args)-1次.很好,因为其中一个可迭代项最长.因此,当我们提到IndexError升高时,这意味着我们已经完成了对args中最长的迭代的迭代.

Now, as established earlier, we can only iterate over all sentinels together len(args)-1 times before it throws an IndexError. This is fine, because one of the iterables is the longest. So, when we come to the point that the IndexError is raised, that means we have finished iterating over the longest iterable in args.

不客气.

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

P.S.: I hope this is understandable.

这篇关于itertools中的izip_longest:这是怎么回事?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆