全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-19 8 分钟 ✍️ juanwangdev

Python yield from 语法

yield from 用于将迭代任务委托给另一个生成器,简化嵌套迭代代码。

基本用法

对比传统写法

Python
# 传统方式:手动迭代
def chain_manual(*iterables):
    for iterable in iterables:
        for item in iterable:
            yield item


# yield from 方式:自动委托
def chain_from(*iterables):
    for iterable in iterables:
        yield from iterable


list(chain_manual([1, 2], [3, 4]))    # [1, 2, 3, 4]
list(chain_from([1, 2], [3, 4]))      # [1, 2, 3, 4]

扁平化嵌套结构

Python
def flatten(nested):
    "递归展平嵌套列表"
    for item in nested:
        if isinstance(item, list):
            yield from flatten(item)  # 委托给递归调用
        else:
            yield item


nested = [1, [2, 3], [4, [5, 6, [7]]], 8]
print(list(flatten(nested)))  # [1, 2, 3, 4, 5, 6, 7, 8]

委托子生成器

yield from 建立委托生成器与子生成器的双向通道:

Python
def accumulator():
    "累加器子生成器"
    total = 0
    while True:
        value = yield total
        if value is None:
            break
        total += value
    return total  # 返回最终值


def aggregator():
    "委托生成器"
    result = yield from accumulator()  # 接收子生成器返回值
    print(f"最终结果: {result}")
    return result


gen = aggregator()
next(gen)           # 启动,返回 0
gen.send(10)        # 返回 10
gen.send(20)        # 返回 30
gen.send(None)      # 输出: 最终结果: 30,抛出 StopIteration(30)

双向通信

yield from 自动转发 sendthrowclose 调用:

Python
def sub_gen():
    "子生成器"
    received = yield "ready"
    yield f"got: {received}"
    return "done"


def main_gen():
    "主生成器"
    result = yield from sub_gen()
    return f"sub returned: {result}"


gen = main_gen()
print(next(gen))       # ready
print(gen.send("hello"))  # got: hello
try:
    gen.send(None)
except StopIteration as e:
    print(e.value)     # sub returned: done

处理异常

Python
def sub_gen():
    try:
        yield 1
        yield 2
        yield 3
    except ValueError as e:
        yield f"caught: {e}"


def main_gen():
    yield from sub_gen()


gen = main_gen()
print(next(gen))  # 1
print(gen.throw(ValueError, "error"))  # caught: error
print(next(gen))  # 3

协程协作示例

Python
async def task_a():
    yield from range(3)
    return "A done"


async def task_b():
    yield from range(3, 6)
    return "B done"


def run_tasks():
    "顺序执行多个协程"
    result_a = yield from task_a()
    result_b = yield from task_b()
    return f"{result_a}, {result_b}"


gen = run_tasks()
list(gen)  # [0, 1, 2, 3, 4, 5]

实际应用

遍历文件树

Python
import os


def walk_files(directory):
    "递归遍历目录"
    for name in os.listdir(directory):
        path = os.path.join(directory, name)
        if os.path.isdir(path):
            yield from walk_files(path)  # 委托给子目录
        else:
            yield path


# 使用
for file_path in walk_files("/project"):
    print(file_path)

组合多个数据源

Python
def read_chunks(file, size=1024):
    "分块读取文件"
    while chunk := file.read(size):
        yield chunk


def process_files(*paths):
    "处理多个文件"
    for path in paths:
        with open(path, 'rb') as f:
            yield from read_chunks(f)

yield from 执行流程

text
yield from EXPR 执行过程:

1. 获取迭代器:iter(EXPR)
2. 建立双向通道
3. 循环迭代:
   - yield 每个值给调用者
   - 转发 send() 值给子生成器
   - 转发 throw() 异常给子生成器
   - 转发 close() 调用给子生成器
4. 子生成器结束后获取返回值
5. 继续执行后续代码

对比总结

特性for + yieldyield from
代码简洁度较繁琐简洁
双向通信需手动转发自动转发
子生成器返回值无法获取自动获取
异常传播需手动处理自动传播
close()需手动调用自动转发

要点总结

要点说明
委托将迭代任务委托给子生成器
双向通道自动转发 send/throw/close
返回值子生成器 return 值成为 yield from 表达式值
嵌套展平简化递归迭代代码

yield from 是生成器委托的语法糖,建立了主生成器与子生成器的透明通道。

D:\git2\jwdev\articles\PYTHON\进阶\迭代器与生成器\yield from语法.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 Python itertools 模块
下一篇 → Python 无限迭代器
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库