繁体   English   中英

python 列表理解中的可迭代列表理解

[英]python iterable list comprehension in list comprehension

我试图弄清楚为什么我的嵌套列表理解不起作用。 代码:

def myzip(*args):
    try:
        x = [iter(i) for i in [*args]]
        while True:
        # for i in range(5):
            yield [next(ii) for ii in x]
            # I want to know why the commented line below won't work
            # yield [next(ii) for ii in [iter(i) for i in [*args]]]
            # or why this outputs [1, 'a']
            # return [next(ii) for ii in [iter(i) for i in [*args]]]
    except:
        pass


def main():
    print(list(myzip([1, 2, 3, 4, 5], ['a', 'b', 'c'])))

if __name__ == '__main__':
    main()

如果我将[iter(i) for i in [*args]]分配给x ,然后使用此列表理解[next(ii) for ii in x]一切正常。 output 将是:

[[1, 'a'], [2, 'b'], [3, 'c']]

但是,如果我尝试省略变量x并在一个更大的列表理解(注释行) [next(ii) for ii in [iter(i) for i in [*args]]]中执行它,它将进入无限循环。 如果将无限循环替换为 for 循环(注释行),则 output 为:

[[1, 'a'], [1, 'a'], [1, 'a'], [1, 'a'], [1, 'a']]

此外,如果我尝试return [next(ii) for ii in [iter(i) for i in [*args]]]它只会返回:

[1, 'a']

有人能告诉我这是为什么吗?

所以我不打算直接回答你的问题(因为评论很好地涵盖了这一点),但我将展示如何将其作为一个可怕的单线来完成,只是为了好玩:

def my_zip(*args):
    yield from iter(lambda data=[iter(a) for a in args]: [next(d) for d in data], None)

有三个部分。

  • iter的第一次使用,在yield from之后,创建了一个callable_iterator 这将重复调用它的第一个参数( lambda ),直到它看到它的第二个参数(哨兵值,在这种情况下为None )或者它遇到任何异常时遇到StopIteration错误 (在这种情况下,它将是一个StopIteration异常。
  • lambda中,我有一个data的默认值,它是您要迭代的迭代器的列表。 这被创建一次,因此对 function 的每个后续调用都将引用它。
  • 最后,在lambda的主体中,我在每个 function 调用中手动将data中的每个迭代器推进一次。 这将一直持续到其中一个迭代器用尽,此时将引发StopIteration 如您所见,在这种情况下,哨兵值无关紧要,因为第一个iter调用将在它获得StopIteration后立即退出,这将冒泡到list使用者,这会导致它停止迭代 由于异常,哨兵值无关紧要。

最后:请永远不要在实际代码中实际执行此操作。


编辑:一些样品 output

In [90]: list(my_zip('abcd', [1,2,3]))
Out[90]: [['a', 1], ['b', 2], ['c', 3]]

In [91]: list(my_zip('abcd', [1,2,3,4,5,6]))
Out[91]: [['a', 1], ['b', 2], ['c', 3], ['d', 4]]

解释编辑:向@superb rain 致敬,感谢他们在下面的聪明评论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM