python - 列表理解引发 RuntimeError
问题描述
为什么这段代码运行良好并且不抛出异常?
def myzip(*args):
iters = [iter(arg) for arg in args]
try:
while True:
yield tuple([next(it) for it in iters])
except StopIteration:
return
for x, y, z in myzip([1, 2], [3, 4], [5, 6]):
print(x, y, z)
但是如果这条线
yield tuple([next(it) for it in iters])
替换为
yield tuple(next(it) for it in iters)
然后一切都停止工作并抛出一个RuntimeError
?
解决方案
这是 Python 3.5 中引入的一个特性,而不是一个 bug。根据PEP-479,当从生成器内部引发RuntimeError
a 时,会有意重新引发StopIteration
a ,这样基于生成器的迭代现在只能在生成器返回时停止,此时StopIteration
会引发异常以停止迭代。
否则,在 Python 3.5 之前,StopIteration
生成器中任何地方引发的异常都会停止生成器而不是传播,因此在以下情况下:
a = list(F(x) for x in xs)
a = [F(x) for x in xs]
F(x)
如果在迭代过程中的某个时刻引发StopIteration
异常,前者会得到截断的结果,这使得调试变得困难,而后者会传播从F(x)
. 该功能的目标是使两个语句的行为相同,这就是更改影响生成器但不影响列表推导的原因。
推荐阅读
- java - 如何使用 Gmail API (Java) 插入带有附件的邮件
- javascript - 如何计算文本或字符串中的表情符号
- maven - 未能向 OpenDayLight 添加新功能
- ios - 在 Cordova 中使用 Button 进行登录验证后重定向
- amazon-s3 - AWS -s3 存储桶区域问题
- java - 如何创建填充并返回现有或新集合的通用方法?
- css - Bootstrap 标题下的全高列
- ios - 调整 Apple MKMapView 标签的大小
- android - 关于三星 Note 9 的通知不起作用
- scala - 如何将列表列表转换为 Scala 中的列表?