今天我正在调试一个奇怪的问题。这个程序很复杂,但是我把这个部分简化为只有几条线来重现奇怪的行为。
在示例中,我连续三次测试随机生成器。如果所有三个测试都返回True,则测试完成。如果没有,必须从头开始重复测试。
函数func1
正常工作。具有func2
的函数any()
应该等同于func1
,但事实并非如此。它不起作用,它会产生错误。 func3
也被打破,这是一个无限繁忙的循环。
问题出在哪里?以yield from
之外的其他方式使用value = yield from ...
是合法的吗?我没有在文档中找到任何内容(到目前为止):
当使用yield from时,它将提供的表达式视为a subiterator。该子转换器生成的所有值都将被传递 直接到当前生成器方法的调用者。
# Python 3.3 or newer
import random
def yield_random():
if random.choice((True, False)):
yield "OK"
return True
return False
def func1():
# only this function works fine
ok3 = False
while not ok3:
for i in range(3):
ok1 = yield from yield_random()
if not ok1:
print("-- not ok")
break
else:
print("All 3 ok !")
ok3 = True
def func2():
# does not work
ok3 = False
while not ok3:
ok3 = all((yield from yield_random()) for i in range(3))
print("All 3 ok !")
def func3():
# does not work
while any(not (yield from yield_random()) for i in range(3)):
print("-- not ok")
print("All 3 ok !")
for x in func1():
print("got:", x)
答案 0 :(得分:2)
func1
是返回生成器的函数,而func2
和func3
是常规函数:
>>> type(func1())
<class 'generator'>
>>> type(func2())
All 3 ok !
<class 'NoneType'>
那是因为:
ok3 = all((yield from yield_random()) for i in range(3))
实际上相当于:
def _gen():
for i in range(3):
r = yield from yield_random()
yield r
ok3 = all(_gen())
由于yield from
语句封装在生成器中,因此此代码不会产生任何结果。您甚至可以在控制台中的函数外部运行它,例如:
>>> all((yield from yield_random()) for i in range(3))
False
虽然它可能不符合您的期望:
>>> list((yield from yield_random()) for i in range(3))
['OK', True, False, False]