Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python izip#u在itertools中最长:什么';这是怎么回事?_Python_Itertools - Fatal编程技术网

Python izip#u在itertools中最长:什么';这是怎么回事?

Python izip#u在itertools中最长:什么';这是怎么回事?,python,itertools,Python,Itertools,我很难理解下面的代码是如何工作的。它来自,是纯python的izip_最长迭代器的等价物。我对sentinel功能特别困惑,它是如何工作的 def izip_longest(*args, **kwds): # izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D- fillvalue = kwds.get('fillvalue') def sentinel(counter = ([fillvalue]*(l

我很难理解下面的代码是如何工作的。它来自,是纯python的izip_最长迭代器的等价物。我对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
中每个iterable的一个填充值减去一。因此,对于上面的示例
['-']
<代码>计数器随后被分配该列表的-功能
sentinel
本身是一个在每次迭代时从该列表中弹出一个项目的列表。您可以在
sentinel
返回的每个迭代器上迭代一次,它将始终生成
fillvalue
sentinel
返回的所有迭代器生成的项目总数是
len(args)-1
(感谢Sven Marnach澄清了这一点,我误解了它)

现在看看这个:

iters = [chain(it, sentinel(), fillers) for it in args]
这就是诀窍
iters
是一个列表,其中包含
args
中每个iterable的迭代器。每个迭代器都执行以下操作:

  • args
    迭代相应iterable中的所有项
  • 在sentinel上迭代一次,生成
    fillvalue
  • 永远重复
    fillvalue
  • 现在,如前所述,我们只能在所有哨兵一起迭代
    len(args)-1次,然后它抛出
    索引器。这很好,因为其中一个是最长的。因此,当我们提到
    索引器
    时,这意味着我们已经完成了对
    args
    中最长的iterable的迭代

    不客气


    附言:我希望这是可以理解的。

    哨兵的定义几乎等同于

    def sentinel():
        yield ([fillvalue] * (len(args) - 1)).pop()
    
    fillvalue_list = [fillvalue] * (len(args)-1)
    def sentinel():
        yield fillvalue_list.pop()
    

    除了它将
    pop
    绑定方法(函数对象)作为默认参数之外。默认参数在函数定义时计算,因此每次调用
    izip_longest
    一次,而不是每次调用
    sentinel
    一次。因此,函数对象“记住”列表
    [fillvalue]*(len(args)-1)
    ,而不是在每次调用中重新构造该列表。

    函数
    sentinel()
    只返回一次生成
    fillvalue
    的迭代器。
    sentinel()
    返回的所有迭代器生成的
    fillvalue
    s总数限制为
    n-1
    ,其中
    n
    是传递给
    izip_longest()
    的迭代器数。在用完此数量的
    fillvalue
    s后,对
    sentinel()
    返回的迭代器进行进一步迭代将产生
    索引器

    此函数用于检测是否已耗尽所有迭代器:每个迭代器都使用
    sentinel()
    返回的迭代器进行
    chain()
    ed。如果所有迭代器都已用尽,则
    sentinel()
    返回的迭代器将被第次迭代
    n
    ,从而生成
    索引器
    ,依次触发
    izip_longest()
    的结束

    到目前为止,我解释了
    sentinel()
    的功能,而不是它的工作原理。调用
    izip_longest()
    时,将计算
    sentinel()
    的定义。在计算定义时,还会计算
    sentinel()
    的默认参数,每次调用
    izip\u longest()
    一次。代码相当于

    def sentinel():
        yield ([fillvalue] * (len(args) - 1)).pop()
    
    fillvalue_list = [fillvalue] * (len(args)-1)
    def sentinel():
        yield fillvalue_list.pop()
    
    将其存储在默认参数而不是封闭范围内的变量中只是一种优化,在默认参数中包含
    .pop
    ,因为每次迭代
    sentinel()
    返回的迭代器时都可以省去查找。

    此外,
    sentinel()
    可以无限次调用,不会引发任何异常。