生成器函数在列表和生成器表达式上表现不同?

时间:2015-10-23 13:23:43

标签: python python-3.x iterator generator

所以我编写了这个无用的生成器函数,它消耗了迭代器的前4个元素:

def f(it):
    for _ in range(2):
        for _, x in zip(range(2), it):
            yield x

以下示例符合我的预期:

y = (x for x in range(4))
for x in f(y):
    print(x)
0
1
2
3

这个例子让我很困惑:

for x in f([0, 1, 2, 3]):
    print(x)
0
1
0
1

为什么两个输出不同?

2 个答案:

答案 0 :(得分:1)

列表可迭代但不是迭代器。如果在传递之前从列表中创建迭代器,您将看到与生成器表达式相同的行为:

>>> list(f(iter([0, 1, 2, 3])))
[0, 1, 2, 3]

迭代器消耗迭代器,所以当你第二次通过迭代器时zip

>>> i = iter([0, 1, 2, 3])
>>> zip(range(2), i)
[(0, 0), (1, 1)]
>>> zip(range(2), i)
[(0, 2), (1, 3)]
>>> zip(range(2), i)
[]

但是当您zip列表再次启动它时,创建一个新的迭代器:

>>> l = [0, 1, 2, 3]
>>> zip(range(2), l)
[(0, 0), (1, 1)]
>>> zip(range(2), l)
[(0, 0), (1, 1)]
>>> zip(range(2), l)
[(0, 0), (1, 1)]

答案 1 :(得分:0)

这是因为列表不是迭代器,而是列表。第一种情况发生的是消耗迭代器。在第二种情况下,它从头开始。您需要执行@user