很长一段时间以来,我都不知道不能将return
放在yield语句前面。但实际上你可以:
def gen():
return (yield 42)
类似于
def gen():
yield 42
return
我能想到的唯一用法是将发送值附加到StopIteration
:pep-0380
在生成器中返回expr会导致StopIteration(expr)被引发在离开发电机时。
def gen():
return (yield 42)
g = gen()
print(next(g)) # 42
try:
g.send('AAAA')
except StopIteration as e:
print(e.value) # 'AAAA'
但这也可以使用一个额外的变量来完成,这个变量更明确:
def gen():
a = yield 42
return a
g = gen()
print(next(g))
try:
g.send('AAAA')
except StopIteration as e:
print(e.value) # 'AAAA'
因此,return (yield xxx)
似乎只是一种句法糖。我是不是错过了什么?
在生成器内部,表达式(yield 42)将生成值42,但如果使用next(generator)
,它也会返回一个None值,如果使用generator.send(value)
,则返回一个给定值。
正如你所说,你可以使用一个中间值来获得相同的行为,不是因为这是语法上的糖,而是因为yield表达式实际上是在返回你发送的值
你同样可以做一些类似的事情
def my_generator():
return (yield (yield 42) + 10)
如果我们调用这个,使用调用序列:
g = my_generator()
print(next(g))
try:
print('first response:', g.send(1))
print('Second response:', g.send(22))
print('third response:', g.send(3))
except StopIteration as e:
print('stopped at', e.value)
首先,我们得到42的输出,生成器基本上处于暂停状态,您可以描述为:return (yield <Input will go here> + 10)
,如果我们调用g.send(1)
,我们得到输出11。并且发电机现在处于以下状态:return <Input will go here>
,然后发送g.send(22)
将抛出StopIteration(22)
,这是因为生成器中处理返回的方式。因此,由于出现异常,您永远无法进行第三次发送。
我希望这个例子能让我们更清楚地了解yield
是如何在生成器中工作的,以及为什么return (yield something)
语法没有什么特别或奇特之处,并且完全按照您的预期工作
至于字面上的问题,你什么时候会这样做?好吧,当你想要产生一些东西,然后稍后返回一个StopIteration,以响应用户发送给生成器的输入。因为这就是代码的字面意思。我预计这种行为很少被人想要。