【问题标题】:What does a return do when using a "yield from" expression?使用“yield from”表达式时,return 有什么作用?
【发布时间】:2016-01-07 06:14:54
【问题描述】:

我无法从yield fromexpression 中找到任何返回值示例。我试过这个简单的代码,但没有成功:

def return4():
    return 4


def yield_from():
    res = yield from range(4)
    res = yield from return4()


def test_yield_from():
    for x in yield_from():
        print(x)


test_yield_from()

产生:

» python test.py 
0
1
2
3
Traceback (most recent call last):
  File "test.py", line 52, in <module>
    test_yield_from()
  File "test.py", line 48, in test_yield_from
    for x in yield_from():
  File "test.py", line 44, in yield_from
    res = yield from return4()
TypeError: 'int' object is not iterable

但我期待:

» python test.py 
0
1
2
3
4

因为,正如 PEP 中所述:

此外,当迭代器是另一个生成器时,允许子生成器执行带有值的 return 语句,该值成为 yield from 表达式的值。

显然,我没有得到这个解释。关于yield from,“子生成器”中的return 是如何工作的?

【问题讨论】:

  • 我不知道。我正在尝试它,因为我没有找到任何示例。这就是我在这里问的原因,很明显。

标签: python python-3.x yield-from


【解决方案1】:

yield from generator

的缩写
for i in generator:
    yield i

嗯,它比这更复杂一点:https://www.python.org/dev/peps/pep-0380/#formal-semantics

如果generator = 4,这将无法正常工作。 (您的return4() 不是生成器。它是函数。)

为了得到你想要的东西,你只需这样做:

def yield_from():
    yield from range(4)
    yield 4

【讨论】:

  • 当然。那么,子生成器中的 return 语句是做什么的呢?什么意思:“允许子生成器执行带有值的return语句,并且该值成为yield from表达式的值”
  • 你调用你的函数:return4()。在执行yield from 时,这已经评估为4
  • @jeckyll2hide 如果你有def range4(): return range(4),那么即使range4 不是生成器,你也可以使用yield from range4()
  • @Trengot ...这可能比我的尝试更好地回答了这个问题。
  • @Trengot:不,这不是我(和 PEP)所说的。我说的是从子生成器返回 values,而不是返回生成器。
【解决方案2】:

生成器可以在耗尽时返回一个值:

def my_gen():
    yield 0
    return "done"

g = my_gen()
next(g)
next(g) # raises StopIteration: "done"

yield from 语句中的返回值就是这个值。例如。

def yield_from():
    res = yield from my_gen()
    assert res == "done"

默认情况下,此值为None。也就是说res = yield from range(4) 将设置resNone

【讨论】:

  • 好的,这似乎更清楚了。这个的用例是什么?例如,我会用它来将普通函数重构为子生成器吗?
  • 子生成器和从生成器返回在 python 的协程库中被大量使用。 --docs.python.org/3/library/asyncio-task.html。这里生成器用于创建协作多线程,而不是产生值。
【解决方案3】:

我正在为您的测试发布一个工作示例。

return4 函数现在是一个生成器。要实现这一点,函数中的任何位置都必须存在 yield(Python 3.5 中有一个新的相关功能,但现在这并不重要)。

正如你已经引用的那样:

此外,当迭代器是另一个生成器时,子生成器 允许执行带有值的 return 语句,并且该值 成为表达式的产量值

总结:你会得到一个值。您可以打印它,例如:

def yield_from():
    # ...
    val = yield from return4()
    print("value:", val)  # prints value: 4

但你想输出它,而不是打印。完整代码如下:

def return4():
    if False:
        yield None
    return 4

def yield_from():
    yield from range(4)
    yield (yield from return4())

def test_yield_from():
    for x in yield_from():
        print(x)

test_yield_from()
# prints numbers 0 to 4

您可能会问自己,它有什么用。当您只从生成器接收值时,几乎没有任何优势。但是yield from 在向生成器发送值时是一个很棒的功能。尝试找到对 python 协程的一个很好的解释。太棒了。

【讨论】:

    猜你喜欢
    • 2018-02-22
    • 2017-09-18
    • 2020-05-30
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 2015-01-14
    • 2016-06-01
    • 2020-09-06
    相关资源
    最近更新 更多