很长一段时间我都不知道你不能把return
放在收益率声明面前。但实际上你可以:
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)
只是一个语法糖。我错过了什么吗?
答案 0 :(得分:7)
在生成器内部,表达式(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回显发送给发生器的用户的输入。因为这实际上是代码所说的内容。我希望这种行为很少被人想要。