Python: 生成器,yield

【python】python实现杨辉三角的三种方法 杨辉三角是一种数学图形,由数字排列成类似三角形的形状。它的每个数值等于它上方两个数值之和。这个三角形的形状可以用一个二维表格来表示,其中每个位置上的数值都是通过前一行的数值计算得到的。在这个三角形中,第一行只有一个数值1,第二行有两个数值1,第三行有三个数值1,以此类推。从第四行开始,除了首尾的1之外,中间的数值是上一行对应位置的两个数值之和。对称性:杨辉三角以中心轴为对称轴,每行的对称位置上的数值相等。 阅读详情

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator.

最难理解的是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

示例:

 

#############################################################################################

以下引用自:https://www.liaoxuefeng.com/wiki/1016959663602400/1017318207388128

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。

我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?

如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

我们讲过,generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

当然,上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:

>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)
... 
0
1
4
9
16
25
36
49
64
81

所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。(for 循环会自动调用生成器的next()函数)

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'

注意,赋值语句:

a, b = b, a + b

相当于:

t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]

但不必显式写出临时变量t就可以赋值。

上面的函数可以输出斐波那契数列的前N个数:

>>> fib(6)
1
1
2
3
5
8
'done'

仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'

这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>

这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

举个简单的例子,定义一个generator,依次返回数字1,3,5:

def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)

调用该generator时,首先要生成一个generator对象,然后用next()函数不断获得下一个返回值:

>>> o = odd()
>>> next(o)
step 1
1
>>> next(o)
step 2
3
>>> next(o)
step 3
5
>>> next(o)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

可以看到,odd不是普通函数,而是generator,在执行过程中,遇到yield就中断,下次又继续执行。执行3次yield后,已经没有yield可以执行了,所以,第4次调用next(o)就报错。

回到fib的例子,我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代:

>>> for n in fib(6):
...     print(n)
...
1
1
2
3
5
8

但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:

>>> g = fib(6)
>>> while True:
...     try:
...         x = next(g)
...         print('g:', x)
...     except StopIteration as e:
...         print('Generator return value:', e.value)
...         break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done

关于如何捕获错误,后面的错误处理还会详细讲解。

Python yield生成器:从内存优化到send/yield from全解析 Python生成器是惰性求值思想的典型实现,通过yield关键字将普通函数变为可暂停、可恢复的状态机,从而避免一次性加载海量数据。在处理数亿行日志或无限序列时,生成器能大幅降低内存占用,而列表推导式则可能导致进程崩溃。理解yield与return的本质区别,掌握send双向通信、yield from委托机制以及StopIteration的传递规则,是深入理解协程与异步编程的基础。本文结合一次真实的内存爆炸线上事故,系统梳理生成器执行机制、进阶用法、面试高频考点与实用建议,帮助开发者在数据清洗、日志解析等场景 阅读详情

相关推荐

Python生成器:理解yield关键字

生成器是一种迭代器,它可以通过yield关键字逐个生成值。与普通函数不同,生成器函数在每次调用时不会重新运行整个函数,而是从上次暂停的地方继续执行,直到遇到下一个yield语句。这种特性使得生成器非常适合处理大数据流或无限序列,因为它可以按需生成值,而无需一次性将所有值加载到内存中。生成器是 Python 中一种强大的工具,通过yield关键字,可以实现惰性计算和高效的内存管理。生成器适用于处理大数据流、无限序列和管道式数据处理。掌握生成器的使用方法和高级特性,可以帮助你编写出更高效、更简洁的代码。

ifree_code的博客 716

Python生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种

叫我二当家的专栏 720

《Python 异步之光:全面理解 yield、yield from 与生成器协程的奥秘》

本文深入探讨了Python中yield和yield from关键字的原理与应用,揭示了它们如何构建生成器和协程。文章首先介绍了yield创建惰性迭代器的优势,包括内存节省和可读性提升;然后解析了yield from作为生成器"接力棒"的作用,简化了多层生成器组合;最后对比了生成器协程与现代async/await语法,提供了实际应用场景中的最佳实践建议。通过爬虫数据处理、文本处理管道等实例,展示了这些机制如何优化程序性能与可维护性,并展望了它们它们在未来Python异步生态中的发展前景。

铭渊老黄 967

python crop image_Keras 在fit_generator训练方式中加入图像random_crop操作

使用Keras作前端写网络时,由于训练图像尺寸较大,需要做类似 tf.random_crop 图像裁剪操作。为此研究了一番Keras下已封装的API。Data Augmentation(数据扩充)Data Aumentation 指使用下面或其他方法增加输入数据量。我们默认图像数据。旋转&反射变换(Rotation/reflection): 随机旋转图像一定角度; 改变图像内容的朝向;翻转变换(f...

weixin_39821035的博客 411

python123题目——个税计算器

类型:简单分支。

m0_62488776的博客 5803

深入解析SerDes系统中的时钟数据恢复电路(CDR)——基于Cadence的PLL/Bang-Bang/PS-PI架构实现与仿真

本文深入解析SerDes系统中的时钟数据恢复电路(CDR),重点探讨基于Cadence平台的PLL、Bang-Bang和PS-PI三种架构的实现与仿真。通过详细的技术对比和工程实践案例,揭示CDR在高速串行通信中的关键作用,并提供TSMC 28nm工艺下的优化策略与故障排查经验,助力工程师应对10Gbps以上SerDes设计挑战。

weixin_29202687的博客 253

python打印杨辉三角,直角形和正三角形的杨辉三角

:python编程实现,打印直角形的杨辉三角,要求输入一个正整数n,表示打印的杨辉三角形层数,输入杨辉三角。在此基础上,实现打印正三角形的杨辉三角

c1007857613的专栏 4798

Eplan P8 API二次开发--插入符号(Symbol)功能(Function)并定义属性

1、目的 使用Eplan API在页中自动插入某个符号并按约定规则自动设置好属性 2. 步骤 一、基础信息 比如要在Eplan中自动插入一个电机的符号并定制属性,我们先要确定要插入的符号名,可以在Eplan中获取如下符号(Symbol)信息 可以知道我们待插入的符号名称为M3_1, 接下来,使用Visual Studio建立类库项目,并引用Eplan Api库 二、获取符号变量(SymbolVariant) 在Eplan中,当一个符号(Symbol)被插入到页中,这个符号的引用即变为一个(Function

如是道程序人生 4529

python杨辉三角_Python实现杨辉三角,超详细!

deftriangles():N=[1]   #初始化为[1],杨辉三角的每一行为一个listwhileTrue:yieldN  #yield 实现记录功能,没有下一个next将跳出循环,S=N[:]   #将list N赋给S,通过S计算每一行S.append(0) #将list添加0,作为最后一个元素,长度增加1N=[S[i-1]+S[i] for i inrange(len(S))]  #通...

weixin_39701288的博客 487

笔试题-2023-星宸-数字IC设计【纯净题目版】

4 笔试题-2023-星宸-数字IC设计【纯净题目版】

w0shishabi的博客 1172

智能车图像处理12-进阶篇4--环岛辅助判断条件

主函数: 第6行: 含义是当前需要不在坡道和车库状态 第11-12行 : 寻找一下环岛的双断点(在辅助函数中) 第16-66行: 当左右线的方差满足一边很大,一边很小时,truepianfangflag /truepianfangflagforleft 置1,在环岛的判断中使用。 辅助函数: 双断点函数(左与右相似,以做为例): 第13-28行: 第一处断点 第29-40行: 第一处断点后 连续边线 第41-52行: 第一处连续后,第二处断点 第53-64行: 第二处断点后,第二处

taiyuezyh的博客 1万+

Python 生成器基础:yield 核心原理

在Python开发领域,2026年的今天,生成器(Generator)早已不是什么小众高级语法,而是成为了Pythonic编程的核心基石之一。无论是日常数据处理、海量文件读取,还是异步编程、AI数据流水线,yield关键字都无处不在。但对于很多刚入门Python的小白,甚至有一两年开发经验的同学来说,yield始终像一层窗户纸——看着简单,一用就懵,到底它和普通return有啥区别?生成器凭什么能省内存?迭代的时候到底发生了什么?

HHX_01的博客 784

DeepSeek Harness 工程实践与高级特性:从测试到安全的完整指南

AI Agent 能执行命令、读写文件、自主决策,能力越强风险越大——删文件、泄密钥、死循环、竞态条件随时可能发生。本文是 DeepSeek Harness 系列第三篇,深入剖析其工程实践与高级特性:从单元测试到真实 API 冒烟测试的分层策略,拒绝 Mock 依赖、坚持"验证世界而非自我报告";从正交结果、规范化契约到 Dispose 静止的防御式编程铁律;以及跨平台多层进程沙箱、文件系统版本守卫、fail-closed 审批机制、模型编写的工作流引擎与上下文压缩等高级能力。

program哲学 207

python中生成器:yield,yield from

Python生成器是一种特殊的可迭代对象,通过yield语句逐步返回值,避免一次性加载所有数据到内存。生成器函数在调用时返回生成器对象,每次next()调用从上次暂停处继续执行,直到遇到下一个yield或结束。yield from语法可简化生成器委托写法,自动传递子生成器的值。生成器适用于大规模数据流处理(如逐行读取文件),具有内存高效、状态保留等特点,是理解Python协程和异步编程的基础。

keyboard专栏 430

Python爬虫实战:高效爬取Vimeo高清视频

在当今数字化时代,视频内容已成为互联网的重要组成部分。Vimeo作为一个高质量的视频分享平台,拥有大量优质视频资源。然而,Vimeo并未提供直接下载视频的选项,因此,我们需要借助Python爬虫技术来获取这些高清视频。(HTTP Live Streaming)格式存储。Vimeo的视频通常不会直接暴露。Vimeo的视频通常以。

2201_76125261的博客 432

【测开求职】面试题:计算机网络 详细版整理

本篇文章是笔者为准备研究生复试和校招而写,因此主要针对问答,注重理解,而不在于细节计算。读者可以先查看上面的链接走一遍计算机网络的整体框架结构。其中,重点难点以及易混淆的知识点,笔者会用其他文章进行了详述,在知识点处贴好了链接,有需要的可以查阅。

vector的博客 5937

掌握内存的艺术:Python生成器与 yield 完全解析

本文深入解析Python生成器与yield关键字的原理与应用。生成器通过yield实现惰性求值,避免一次性加载大数据导致的内存溢出问题。文章首先阐述迭代器协议基础,然后详细讲解yield的工作原理,展示其暂停执行和恢复状态的特性。通过四个实战案例(无限序列生成、大文件读取、数据处理管道、协程基础)演示生成器的强大功能,并介绍生成器表达式的简洁用法。最后提出高级特性yield from的使用建议和最佳实践,强调生成器在内存效率和处理大数据方面的优势。掌握生成器可显著提升Python编程水平,实现更高效优雅的代

ZTLJQ的博客 635

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Python生成器:yield的使用

生成器概述通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种

爱橙子的OK绷的专栏 1978

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【重学Python】:Python 生成器之细说 yield

从上面的例子中函数 self_return(n) 被调用的过程中我们可以清晰的看出,s = self_return(3) 函数体内的语句就开始执行了,遇到 return 以后将值返回,并结束在函数体内的执行,所以我们看到的结果是 return 后面的语句根本没有执行,这个是 return 的特点,不知道你还记得么?通过上面的继续操作,我们可以看到每次遇到 yield 的时候都会返回值,并且暂停,下次再执行的时候是从上次暂停的位置开始又继续执行的,当没有满足条件的值,就会抛出异常。(安全链接,放心点击)

aobulaien001的博客 893

Python中的yield:生成器的魔力解析

在本文中,深入探讨了Python中yield的强大特性以及生成器的广泛应用。通过详实的示例代码,首先介绍了yield的基本用法,将普通函数转变为生成器函数,实现了一种惰性计算的方式。进一步深入了解生成器的工作原理,了解了生成器状态的保存与恢复,以及无限生成器的应用场景。进阶部分介绍了yield from的用法,它通过简化了委托生成器和递归生成器的实现,使得代码更为清晰和简洁。还深入探讨了异常处理与生成器的结合,以及yield的高级用法,包括双向通信和协程的实现。

涛哥聊Python 1319

Python:生成器函数,yield from

引入 生成器generator:生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,调用这个函数得到一个生成器对象 生成器函数: 函数体中包含yeild语句的函数,返回生成器对象 生成器对象,是一个可迭代对象,是一个迭代器 生成器对象,是延迟求值,惰性求值的 yield与return的比较 遇到yield,函数就会让出此次操作,去执行函数体别的语句 return,直接打断函数的执行,返回结果 普通函数,生成器函数的比较 例子一: 单个yiel

二十四桥明月夜 461

复盘:python知识:什么是生成器yield

1)使用生成器yield的好处有俩:节省内存空间 2)提升代码运行速度 3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

weixin_46838716的博客 314

Python yield深度解析:生成器原理、内存优化与工程实战

生成器是Python中实现惰性求值和内存高效迭代的核心机制,其本质是编译期生成的状态机对象,依托迭代协议与栈帧挂起/恢复实现按需计算。yield并非语法糖,而是协程调度在用户态的显式让渡,通过gi_frame精准控制局部变量生命周期,使内存占用恒定于KB级,远优于列表推导式。结合send()、throw()、yield from等接口,可构建实时数据流处理、异步任务协调、配置热更新等高可靠性系统。本文深入CPython源码层面,解析生成器状态机、字节码指令(YIELD_VALUE)、委托协议及资源管理陷阱,

weixin_31240035的博客 214

Python:生成器yield介绍

是一个用于定义生成器函数的关键字。生成器函数可以用于按需生成序列的元素,而不是一次性生成所有元素。关键字,可以将生成器函数转变为一个生成器对象。当调用生成器对象的时候,可以逐个获取生成器函数中。生成器函数和生成器对象提供了一个灵活且高效的方式来处理大型数据集或需要按需生成序列的场景。每次调用生成器对象时,生成器函数会从上一次。需要注意的是,一旦生成器函数执行完毕(即没有更多的。的生成器函数,用于生成从 1 到指定数字。函数时,生成器函数会从上一次。函数逐个获取生成器函数中。创建了一个生成器对象。

canGfly的博客 200

Python 关键字yield:生成器的魔法

生成器是一种特殊的迭代器,它可以在需要的时候生成值,而不是一次性生成所有的值并存储在内存中。这使得生成器在处理大量数据时非常高效,因为它只在需要的时候生成值,避免了内存的过度占用。yield关键字是 Python 中一个非常强大的工具,它为我们带来了生成器的概念,使得我们能够以一种高效且灵活的方式处理大量数据。通过理解yield的用法和关键要点,我们可以在实际编程中充分发挥生成器的优势,提高程序的性能和可维护性。

liuhailong0511的博客 1416

【Python生成器进阶指南】:深入掌握yield from的5大核心使用场景

掌握Python生成器yield from使用场景,高效解决嵌套迭代问题。本文详解其在递归生成器、协程通信、扁平化序列等5大核心场景的应用方法,提升代码可读性与性能,值得收藏。

InitPulse的博客 962
上一篇: python : 自定义可迭代类,__iter__ ,__next__的作用
下一篇: Anaconda创建、激活、退出、删除虚拟环境
wzg2016
博客等级 码龄10年 539粉丝 493原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值