关于python:何时使用return(产生一些东西)?

When to use return (yield something)?

很长一段时间我不知道你不能把return放在收益率声明前面。但实际上你可以:

1
2
def gen():
    return (yield 42)

它类似于

1
2
3
def gen():
    yield 42
    return

我唯一能想到的用法是将发送值附加到StopIteration:pep-0380

return expr in a generator causes StopIteration(expr) to be raised
upon exit from the generator.

1
2
3
4
5
6
7
8
9
def gen():
    return (yield 42)

g = gen()
print(next(g))  # 42
try:
    g.send('AAAA')
except StopIteration as e:
    print(e.value)  # 'AAAA'

但这也可以使用一个额外的变量来完成,这更为明确:

1
2
3
4
5
6
7
8
9
10
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),它还返回一个值,如果使用generator.send(value),则该值为无。

正如您所说,您可以使用一个中间值来获得相同的行为,这不是因为这是语法上的糖分,而是因为产量表达式实际上返回了您发送的值。

你也可以做类似的事情

1
2
def my_generator():
    return (yield (yield 42) + 10)

如果我们调用它,使用调用序列:

1
2
3
4
5
6
7
8
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 + 10),如果我们调用g.send(1),我们得到输出11。发电机现在处于以下状态:return ,然后发送g.send(22)将抛出一个StopIteration(22),因为返回是在生成器中处理的。因此,由于出现异常,您永远无法进行第三次发送。

我希望这个例子能更清楚地说明yield在生成器中的工作原理,以及为什么语法return (yield something)没有什么特别之处或异国情调,并且可以按照您的期望工作。

至于字面上的问题,你什么时候做?当你想要生成一些东西时,然后返回一个StopIteration来回送发送给生成器的用户的输入。因为这就是代码的字面意思。我想这种行为很少被人想要。