yield from 关键字的 return 语句

我经常需要写一些比较复杂的代码,常常会遇到各种各样的问题。比如我在使用yield from 表达式时,return 语句的问题。我们知道,在使用 yield from 表达式时,return 语句的作用是在子生成器(被调用的生成器)执行完毕后,返回最终的结果到调用者。这可以让生成器在嵌套结构中更清晰地传递值。具体情况我会一一用文字记录下来,方便后期参考:

1、问题背景

使用 "yield from" 表达式时,return 语句的作用是什么?我在很多示例中都没有找到 return 语句从 yield from 表达式返回的值。我尝试了以下简单的代码,但没有成功:

csharp 复制代码
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 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 语句是如何工作的?

2、解决方案

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

ruby 复制代码
def my_gen():
    yield 0
    return "done"
​
g = my_gen()
next(g)
next(g) # raises StopIteration: "done"

在 yield from 语句中返回的值将是此值。例如:

csharp 复制代码
def yield_from():
    res = yield from my_gen()
    assert res == "done"

默认情况下,此值为 None。即 res = yield from range(4) 会将 res 设置为 None。

答案2:

yield from generator 的简写为:

less 复制代码
for i in generator:
    yield i

好吧,它比这复杂一点:www.python.org/dev/peps/pe... 。如果 generator = 4,则它将无法正常工作。(你的 return4() 不是一个生成器,而是一个函数。)为了得到你想要的结果,你可以这样做:

python 复制代码
def yield_from():
    yield from range(4)
    yield 4

答案3:

我为你提供了测试的一个工作示例。return4 函数现在是一个生成器。为实现这一目标,必须在函数中任何地方出现 yield(Python 3.5 中有一个新的相关特性,但现在并不重要)。

正如你已经引用的:

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

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

python 复制代码
def yield_from():
    # ...
    val = yield from return4()
    print("value:", val)  # prints value: 4

但你希望的是 yield 它,而不是打印它。以下是完整的代码:

python 复制代码
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 协程的良好解释。它很棒。

其实上面的问题我们知道,具体来说,当一个生成器函数中使用 yield from 调用另一个生成器时,return 语句的返回值会成为调用者获取的值。这就允许子生成器产生的值直接传递给调用者,而不需要在父生成器中一个一个地使用 yield 语句传递。所以后期有啥不懂的都可以评论区留言。

相关推荐
喵手6 小时前
Python爬虫零基础入门【第二章:网页基础·第1节】网页是怎么工作的:URL、请求、响应、状态码?
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·网页基础
喵手7 小时前
Python爬虫零基础入门【第二章:网页基础·第4节】新手最常栽的坑:编码、时区、空值、脏数据!
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·python爬虫编码时区·爬虫编码时区
癫狂的兔子7 小时前
【Python】【爬虫】爬取虎扑网NBA排行数据
数据库·爬虫·python
小白学大数据9 小时前
移动端Temu App数据抓包与商品爬取方案
开发语言·爬虫·python
喵手10 小时前
Python爬虫零基础入门【第二章:网页基础·第3节】接口数据基础:JSON 是什么?分页是什么?
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·接口数据基础·爬虫json
极安代理10 小时前
HTTP代理IP如何提升爬虫采集效率?
爬虫·tcp/ip·http
喵手11 小时前
Python爬虫零基础入门【第二章:网页基础·第2节】你要抓的到底是什么:HTML、CSS 选择器、XPath 入门?
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·网页基础·网页结构解析
喵手13 小时前
Python爬虫零基础入门【第一章:开篇与准备·第2节】环境搭建:Python/虚拟环境/依赖/抓包工具一次搞定!
爬虫·python·抓包工具·python爬虫实战·环境准备·python环境配置·python爬虫工程化实战
一招定胜负13 小时前
仅通过提示词用豆包实现项目:爬虫+神经网络对目标图片分类
爬虫·神经网络·分类
咸甜适中14 小时前
双色球、大乐透兑奖分析小程序(rust_Tauri + Vue3 + sqlite)
爬虫·rust·sqlite·vue3·tauri2