百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

揭开 Python yield的神秘面纱

bigegpt 2024-09-17 12:35 4 浏览


在 Python 编程中, yield 语句在异步编程和基于生成器的编程中都起着举足轻重的作用。它在管理数据流和异步操作的效率和简单性方面汇集了两全其美的优势。与提供单一结果和结论的传统函数不同, yield 将函数修改为生成器。这种更改允许函数暂时停止其进程并提供临时结果,

理解 yield

Python 中使用的关键字 yield于将函数转换为生成器。生成器是一种特殊类型的迭代器,它延迟生成值,这意味着它可以动态生成项目并一次迭代一个项目,从而节省内存和处理能力。当一个函数包含至少一个 yield 语句时,它就变成了一个生成器函数。调用此函数时,不会立即执行其主体,而是返回生成器对象。

语法和基本用法

yield 语法很简单:

def generator_function():
    yield value

这里是 value 函数生成回调用方的数据。每次调用生成器 __next__() 的方法时,生成器都会继续执行,直到下一个语句,在该 yield 语句中再次暂停,从而生成另一个值。

yield基础知识

想象一下,你有一个巨大的数字列表,想一个接一个地处理每个数字。如果要使用常规函数一次处理并返回所有结果,则需要将整个已处理数字列表存储在内存中。

yield如何工作?

  1. 执行开始和暂停:当函数包含语 yield 句时,它会自动成为生成器函数。调用此函数时,其代码不会立即执行。相反,它返回一个生成器对象。仅当调用生成器 next() 的方法时,函数的执行才会开始。在遇到 yield 语句时,该函数会输出 after yield 的值,暂停其执行,并记住它在代码中的当前位置。
  2. 恢复执行:下次对生成器对象调用时 next() ,函数将在语 yield 句中断后立即恢复执行。如果遇到另一个 yield 语句,它将再次暂停,返回下一个值,依此类推,直到它到达函数或语 return 句的末尾。语 return 句或到达函数末尾时向生成器发出信号以引发 StopIteration 异常,指示它没有更多值要生成。

为了更好地理解,让我们看一个简单的例子:

def simple_counter(n):
    count = 1
    while count <= n:
        yield count
        count += 1

这里, simple_counter 是一个从 1 数到 max 的生成器函数。每次调用 next() 其生成器对象时,它都会生成序列中的下一个数字:

counter = simple_counter(3)  # Creates a generator object
print(next(counter))  # Outputs: 1
print(next(counter))  # Outputs: 2
print(next(counter))  # Outputs: 3

在生成 3 后,下一个调用将 next(counter) 引发异常 StopIteration ,指示已生成所有值。

使用yield的好处

  • 内存效率:生成器通过一次生成一个项目(仅在需要时)而不是将整个数据集加载到内存中来促进大型数据集的处理。
  • 懒惰:生成器动态计算值并等待下一次调用。这种“惰性”计算非常适合处理数据流,例如从文件中读取数据,您可能不需要或不想将整个文件读入内存。
  • 控制流:它提供了一种简洁的代码编写方式,可以随时间推移生成一系列结果,而不是一次生成所有结果。这可以简化某些算法的逻辑。
  • 代码可读性和可维护性:使用 yield 可以使处理序列的代码更具可读性和易理解性,尤其是在处理复杂的数据管道或流时。
  • 异步编程:在异步操作的上下文中, yield 可以与 async 协程结合使用, await 也可以在协程中使用,从而实现对高性能 Web 应用程序至关重要的非阻塞 IO 操作。

yield的实际应用

数据流

生成器非常适合处理大型数据流,例如逐行读取大型文件。生成器可以一次生成一行,而不是将整个文件读入内存,从而大大减少内存使用量。

这可能与以下情况有关:

  • 数据分析:使用此方法预处理或分析大型数据集,例如日志文件或大型文本数据集,其中每行表示一个数据条目。
  • 文件筛选:筛选出满足特定条件的特定行,例如包含特定关键字或匹配模式的行。
  • 数据转换:在将每一行保存到新文件或进一步处理之前,以某种方式转换每一行。
# Define the generator function for reading large files
def read_large_file(file_name):
    with open(file_name, 'r') as file:
        for line in file:
            yield line.strip()

# Use the function to read and print each line of the file
file_name = 'large_file.txt'  # Specify the path to your large file
for line in read_large_file(file_name):
    print(line)

这种处理文件的方法对于大型数据集特别有用,因为它最大限度地减少了内存使用量,允许处理太大而无法一次放入内存的文件。

实现迭代器

使用生成器可以轻松实现自定义迭代器。这对于创建可以使用 for 循环进行迭代的对象非常有用,而无需手动实现 __iter__() and __next__() 方法:

def count_up_to(max):
    count = 1
    while count <= max:
        yield count
        count += 1

若要使用该 count_up_to(max) 函数(该函数是一个生成器函数,旨在生成从 1 到指定最大值 ( max 的数字),请按照下列步骤操作:

  1. 调用生成器函数:首先,您需要通过调用具有特定 max 值的函数来初始化生成器。这不会启动计数过程,而是准备生成器开始生成值。
  2. 遍历生成器:使用 for 循环遍历生成器对象。在每次迭代中,生成器都会生成下一个数字,直到达到指定的最大值。
  3. 处理每个生成值:在循环中,您可以根据需要处理每个生成值。在最简单的情况下,您可以只打印每个数字。
# Initialize the generator with a max value of 10
number_generator = count_up_to(10)

# Iterate over the generator and print each number
for number in number_generator:
    print(number)

异步编程

在现代 Web 开发中,异步生成器用于高效的数据获取和处理,而不会阻止执行。这在 Web 抓取、API 使用和异步 IO 任务中特别有用:

async def async_generator():
    for item in range(10):
        yield item
        await asyncio.sleep(1)

要使用该 async_generator 函数(Python 中的异步生成器),您需要一个异步环境来运行它。这意味着您将在 async 函数中运行它,并使用 await 关键字将控制权交还给事件循环,同时等待生成器中的下一项。生成器中的 asyncio.sleep(1) 调用模拟异步操作,例如从数据库获取数据或发出 HTTP 请求,方法是在生成下一项之前休眠 1 秒钟。

import asyncio

async def async_generator():
    for item in range(10):
        yield item
        await asyncio.sleep(1)  # Simulate an async operation

async def consume_generator():
    async for item in async_generator():
        print(item)  # Process the item (e.g., print it)

# Run the consume_generator function
asyncio.run(consume_generator())
  • async_generator 函数生成从 0 到 9 的数字,在每次生成之间暂停 1 秒以模拟异步操作。
  • consume_generator async 函数遍历 async_generator using async for .它打印生成器生成的每个项目。
  • asyncio.run(consume_generator()) 调用在事件循环中运行 consume_generator 函数,这是执行异步/await 代码所必需的。

通过使用 async for ,您可以在值可用时使用 , async_generator 循环的每次迭代都会自动处理 await for the next item for the yielded after the sleep period.此模式对于处理异步生成的数据流特别有用,例如来自异步 API 调用或其他异步操作的响应。

相关推荐

方差分析简介(方差分析通俗理解)

介绍方差分析(ANOVA,AnalysisofVariance)是一种广泛使用的统计方法,用于比较两个或多个组之间的均值。单因素方差分析是方差分析的一种变体,旨在检测三个或更多分类组的均值是否存在...

正如404页面所预示,猴子正成为断网元凶--吧嗒吧嗒真好吃

吧嗒吧嗒,绘图:MakiNaro你可以通过加热、冰冻、水淹、模塑、甚至压溃压力来使网络光缆硬化。但用猴子显然是不行的。光缆那新挤压成型的塑料外皮太尼玛诱人了,无法阻挡一场试吃盛宴的举行。印度政府正...

Python数据可视化:箱线图多种库画法

概念箱线图通过数据的四分位数来展示数据的分布情况。例如:数据的中心位置,数据间的离散程度,是否有异常值等。把数据从小到大进行排列并等分成四份,第一分位数(Q1),第二分位数(Q2)和第三分位数(Q3)...

多组独立(完全随机设计)样本秩和检验的SPSS操作教程及结果解读

作者/风仕在上一期,我们已经讲完了两组独立样本秩和检验的SPSS操作教程及结果解读,这期开始讲多组独立样本秩和检验,我们主要从多组独立样本秩和检验介绍、两组独立样本秩和检验使用条件及案例的SPSS操作...

方差分析 in R语言 and Excel(方差分析r语言例题)

今天来写一篇实际中比较实用的分析方法,方差分析。通过方差分析,我们可以确定组别之间的差异是否超出了由于随机因素引起的差异范围。方差分析分为单因素方差分析和多因素方差分析,这一篇先介绍一下单因素方差分析...

可视化:前端数据可视化插件大盘点 图表/图谱/地图/关系图

前端数据可视化插件大盘点图表/图谱/地图/关系图全有在大数据时代,很多时候我们需要在网页中显示数据统计报表,从而能很直观地了解数据的走向,开发人员很多时候需要使用图表来表现一些数据。随着Web技术的...

matplotlib 必知的 15 个图(matplotlib各种图)

施工专题,我已完成20篇,施工系列几乎覆盖Python完整技术栈,目标只总结实践中最实用的东西,直击问题本质,快速帮助读者们入门和进阶:1我的施工计划2数字专题3字符串专题4列表专题5流程控制专题6编...

R ggplot2常用图表绘制指南(ggplot2绘制折线图)

ggplot2是R语言中强大的数据可视化包,基于“图形语法”(GrammarofGraphics),通过分层方式构建图表。以下是常用图表命令的详细指南,涵盖基本语法、常见图表类型及示例,适合...

Python数据可视化:从Pandas基础到Seaborn高级应用

数据可视化是数据分析中不可或缺的一环,它能帮助我们直观理解数据模式和趋势。本文将全面介绍Python中最常用的三种可视化方法。Pandas内置绘图功能Pandas基于Matplotlib提供了简洁的绘...

Python 数据可视化常用命令备忘录

本文提供了一个全面的Python数据可视化备忘单,适用于探索性数据分析(EDA)。该备忘单涵盖了单变量分析、双变量分析、多变量分析、时间序列分析、文本数据分析、可视化定制以及保存与显示等内容。所...

统计图的种类(统计图的种类及特点图片)

统计图是利用几何图形或具体事物的形象和地图等形式来表现社会经济现象数量特征和数量关系的图形。以下是几种常见的统计图类型及其适用场景:1.条形图(BarChart)条形图是用矩形条的高度或长度来表示...

实测,大模型谁更懂数据可视化?(数据可视化和可视化分析的主要模型)

大家好,我是Ai学习的老章看论文时,经常看到漂亮的图表,很多不知道是用什么工具绘制的,或者很想复刻类似图表。实测,大模型LaTeX公式识别,出乎预料前文,我用Kimi、Qwen-3-235B...

通过AI提示词让Deepseek快速生成各种类型的图表制作

在数据分析和可视化领域,图表是传达信息的重要工具。然而,传统图表制作往往需要专业的软件和一定的技术知识。本文将介绍如何通过AI提示词,利用Deepseek快速生成各种类型的图表,包括柱状图、折线图、饼...

数据可视化:解析箱线图(box plot)

箱线图/盒须图(boxplot)是数据分布的图形表示,由五个摘要组成:最小值、第一四分位数(25th百分位数)、中位数、第三四分位数(75th百分位数)和最大值。箱子代表四分位距(IQR)。IQR是...

[seaborn] seaborn学习笔记1-箱形图Boxplot

1箱形图Boxplot(代码下载)Boxplot可能是最常见的图形类型之一。它能够很好表示数据中的分布规律。箱型图方框的末尾显示了上下四分位数。极线显示最高和最低值,不包括异常值。seaborn中...