将列表理解与生成器表达式进行比较时出现意外结果

Psy*_*ath 7 python list generator

我认为我忽略了一些简单的事情,但似乎无法弄清楚到底是什么。请考虑以下代码:

a = [2, 3, 4, 5]

lc = [ x for x in a if x >= 4 ] # List comprehension
lg = ( x for x in a if x >= 4 ) # Generator expression

a.extend([6,7,8,9])

for i in lc:
    print("{} ".format(i), end="")

for i in lg:
    print("{} ".format(i), end="")
Run Code Online (Sandbox Code Playgroud)

我希望两个for循环都会产生相同的结果,所以4 5。但是,打印生成器exp的for循环会打印4 5 6 7 8 9。我认为这与列表理解的声明(在扩展之前声明)有关。但是,为什么生成器的结果与在扩展列表之前也声明过的不同呢?例如内部发生了什么?

MyN*_*leb 4

生成器在您调用它们之前不会被评估,next()这使得它们变得有用,而列表推导式会立即评估。

所以lc = [4,5]在扩展之前就完成了。

lg在开始时仍然是相同的值,因此extend仍然适用于a生成器中尚未完成评估的 ,这意味着a在开始打印它之前它会被扩展,这就是为什么它也会与其余数字一起打印更长的时间。

像这样检查一下:

>>> a = [2, 3, 4, 5]
>>> lg = ( x for x in a if x >= 4 )
>>> next(lg)
4
>>> next(lg)
5
>>> a.extend([6,7,8,9])
>>> next(lg)
6
Run Code Online (Sandbox Code Playgroud)

但是,如果您尝试next()在扩展之前调用额外的函数,您会发现StopIteration生成器此时已耗尽,然后您将无法再调用它。

>>> a = [2, 3, 4, 5]
>>> lg = ( x for x in a if x >= 4 )
>>> next(lg)
4
>>> next(lg)
5
>>> next(lg)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> a.extend([6,7,8,9])
>>> next(lg)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
Run Code Online (Sandbox Code Playgroud)