生成器函数在列表和生成器表达式上的行为不同?
Generator function behaving differently on lists and generator expressions?
所以我写了这个无用的生成器函数,它消耗迭代器的前 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
为什么两个输出不同?
那是因为列表不是迭代器,它是一个列表。第一种情况发生的是它正在消耗迭代器。在第二种情况下,它是从头开始。你需要做 iter([0, 1, 2, 3])
.
列表是可迭代但不是迭代器。如果在传递列表之前从列表创建迭代器,您将看到与生成器表达式相同的行为:
>>> 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)]
所以我写了这个无用的生成器函数,它消耗迭代器的前 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
为什么两个输出不同?
那是因为列表不是迭代器,它是一个列表。第一种情况发生的是它正在消耗迭代器。在第二种情况下,它是从头开始。你需要做 iter([0, 1, 2, 3])
.
列表是可迭代但不是迭代器。如果在传递列表之前从列表创建迭代器,您将看到与生成器表达式相同的行为:
>>> 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)]