【问题标题】:When to use return (yield something)?什么时候使用 return(产生一些东西)?
【发布时间】:2017-09-16 03:50:44
【问题描述】:

很长一段时间我都不知道您不能将return 放在yield 语句前面。但实际上你可以:

def gen():
    return (yield 42)

类似于

def gen():
    yield 42
    return

我能想到的唯一用法是将发送的值附加到StopIterationpep-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) 只是一个语法糖。我错过了什么吗?

【问题讨论】:

  • “但这也可以使用一个额外的变量来完成,这更明确” - 你可以这样说任何return 语句。 return x + y 变为 z = x + y; return zreturn foo() 变为 x = foo(); return xreturn (yield whatever) 这里没有任何特定的内容。
  • 至于StopIteration 参数,您不需要显式访问这些参数;这就是yield from 表达式值的实现方式。它是 API 的已发布部分,但通常不是有趣的部分。

标签: python generator


【解决方案1】:

在生成器中,表达式(yield 42)将产生值 42,但如果您使用 next(generator),它也会返回一个值,如果您使用 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 回显用户发送到生成器的输入。因为这就是代码所说的字面意思。我希望这种行为很少需要。

【讨论】:

  • 有趣。如果我做类似x = (yield 42) 然后yield x + 10,使用g.send,似乎x 变成None,这是预期的吗?为什么x 不成为我传递给send 的东西?
  • @juanpa.arrivillaga 很抱歉,您必须发布一些代码来显示您在做什么。以正确的方式拼凑您正在编写的内容会产生预期的结果,因此您可能没有正确拼凑,因为它不适合您。
猜你喜欢
  • 2014-02-27
  • 1970-01-01
  • 2012-12-28
  • 2022-12-04
  • 1970-01-01
  • 1970-01-01
  • 2015-08-09
  • 1970-01-01
相关资源
最近更新 更多