我试图弄清楚为什么我的嵌套列表理解不起作用。代码:
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]
一切正常。输出将是:[[1, 'a'], [2, 'b'], [3, 'c']]
但是如果我尝试省略变量 x
并在一个更大的列表理解中进行(注释行)[next(ii) for ii in [iter(i) for i in [*args]]]
它进入无限循环。如果将无限循环替换为 for 循环(注释行),则输出为:[[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
error 它遇到任何异常。 (在这种情况下,它将是 StopIteration
异常。lambda
我有 data
的默认值这是您要迭代的迭代器列表。 this 被创建一次,因此对该函数的每次后续调用都将引用 this。 lambda
的正文中, 我手动推进 data
中的每个迭代器每个函数调用一次。这将一直持续到其中一个迭代器耗尽,此时会出现 StopIteration
将被提升。如您所见,在这种情况下,哨兵值无关紧要,因为第一个 iter
调用将在收到 StopIteration
后立即保释这将被冒泡到 list
消费者导致它停止迭代。由于异常,哨兵值无关紧要。 最后:请永远不要在真正的代码中真正做到这一点。
编辑:一些示例输出
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]]
解释编辑:给@superbrain 的帽子提示,感谢他们在下面的聪明评论。
关于列表理解中的python可迭代列表理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63403252/