我正在帮助维护一些现在包含自动化 Python 3.7 测试的代码。这导致我遇到了一些与PEP 479 “更改生成器内部的停止迭代处理”相关的问题。我天真的理解是,您可以使用 try-except 块来修改旧代码以与所有 python 版本兼容,例如
旧代码:
def f1():
it = iter([0])
while True:
yield next(it)
print(list(f1()))
# [0] (in Py 3.6)
# "RuntimeError: generator raised StopIteration" (in Py 3.7;
# or using from __future__ import generator_stop)
变成:
def f2():
it = iter([0])
while True:
try:
yield next(it)
except StopIteration:
return
print(list(f2()))
# [0] (in all Python versions)
对于这个简单的示例,它可以工作,但我发现对于一些更复杂的代码,我正在重构它并没有。这是 Py 3.6 的一个最小示例:
class A(list):
it = iter([0])
def __init__(self):
while True:
self.append(next(self.it))
class B(list):
it = iter([0])
def __init__(self):
while True:
try:
self.append(next(self.it))
except StopIteration:
raise
class C(list):
it = iter([0])
def __init__(self):
while True:
try:
self.append(next(self.it))
except StopIteration:
return # or 'break'
def wrapper(MyClass):
lst = MyClass()
for item in lst:
yield item
print(list(wrapper(A)))
# [] (wrong output)
print(list(wrapper(B)))
# [] (wrong output)
print(list(wrapper(C)))
# [0] (desired output)
我知道A
andB
示例是完全等价的,并且C
case 是与 Python 3.7 兼容的正确方式(我也知道重构为for
循环对于许多示例都是有意义的,包括这个人为的示例)。
但问题是为什么这些例子A
会B
产生一个空列表[]
,而不是[0]
?