为什么这些生成器表达式的行为不同?

2024-04-20 05:49:45 发布

您现在位置:Python中文网/ 问答频道 /正文

这两个代码片段仅在构造列表的方式上有所不同。一个使用[],另一个使用list()。你知道吗

这个函数消耗iterable,然后引发StopIteration

>>> try:
...     iterable = iter(range(4))
...     while True:
...         print([next(iterable) for _ in range(2)])
... except StopIteration:
...     pass
...
[0, 1]
[2, 3]

这个函数消耗iterable并循环打印空列表。你知道吗

>>> try:
...     iterable = iter(range(4))
...     while True:
...         print(list(next(iterable) for _ in range(2)))
... except StopIteration:
...     pass
...
[0, 1]
[2, 3]
[]
[]
[]
etc.

这种行为的规则是什么?你知道吗


Tags: 函数intrue列表forrangeiterablelist
1条回答
网友
1楼 · 发布于 2024-04-20 05:49:45

参考PEP479,它说

The interaction of generators and StopIteration is currently somewhat surprising, and can conceal obscure bugs. An unexpected exception should not result in subtly altered behaviour, but should cause a noisy and easily-debugged traceback. Currently, StopIteration raised accidentally inside a generator function will be interpreted as the end of the iteration by the loop construct driving the generator.

(我的重点)

因此list的构造函数对传递的生成器表达式进行迭代,直到引发StopIteration错误(通过调用next(iterable)而不使用第二个参数)。另一个例子:

def f():
    raise StopIteration # explicitly

def g():
    return 'g'

print(list(x() for x in (g, f, g))) # ['g']
print([x() for x in (g, f, g)]) # `f` raises StopIteration

另一方面,*理解的工作方式不同,因为它们将StopIteration传播给调用者。你知道吗


相关政治公众人物提议的行为如下

If a StopIteration is about to bubble out of a generator frame, it is replaced with RuntimeError, which causes the next() call (which invoked the generator) to fail, passing that exception out. From then on it's just like any old exception.

python3.5添加了^{} feature,可以使用

from __future__ import generator_stop

这种行为在python3.7中是默认的。你知道吗

相关问题 更多 >