Python生成器详解

2023-11-13

生成器本质上也是迭代器,不过它比较特殊。以 list 容器为例,在使用该容器迭代一组数据时,必须事先将所有数据存储到容器中,才能开始迭代;而生成器却不同,它可以实现在迭代的同时生成元素。

也就是说,对于可以用某种算法推算得到的多个数据,生成器并不会一次性生成它们,而是什么时候需要,才什么时候生成。

不仅如此,生成器的创建方式也比迭代器简单很多,大体分为以下 2 步:

  1. 定义一个以 yield 关键字标识返回值的函数;
  2. 调用刚刚创建的函数,即可创建一个生成器。

举个例子:

def intNum():
    print("开始执行")
    for i in range(5):
        yield i
        print("继续执行")
num = intNum()

由此,我们就成功创建了一个 num 生成器对象。显然,和普通函数不同,intNum() 函数的返回值用的是 yield 关键字,而不是 return 关键字,此类函数又成为生成器函数。

和 return 相比,yield 除了可以返回相应的值,还有一个更重要的功能,即每当程序执行完该语句时,程序就会暂停执行。不仅如此,即便调用生成器函数,Python 解释器也不会执行函数中的代码,它只会返回一个生成器(对象)。

要想使生成器函数得以执行,或者想使执行完 yield 语句立即暂停的程序得以继续执行,有以下 2 种方式:

  1. 通过生成器(上面程序中的 num)调用 next() 内置函数或者 __next__() 方法;
  2. 通过 for 循环遍历生成器。

例如,在上面程序的基础上,添加如下语句:

#调用 next() 内置函数
print(next(num))
#调用 __next__() 方法
print(num.__next__())
#通过for循环遍历生成器
for i in num:
    print(i)

程序执行结果为:

开始执行
0
继续执行
1
继续执行
2
继续执行
3
继续执行
4
继续执行

这里有必要给读者分析一个程序的执行流程:

  1. 首先,在创建有 num 生成器的前提下,通过其调用 next() 内置函数,会使 Python 解释器开始执行 intNum() 生成器函数中的代码,因此会输出“开始执行”,程序会一直执行到yield i,而此时的 i==0,因此 Python 解释器输出“0”。由于受到 yield 的影响,程序会在此处暂停。
  2. 然后,我们使用 num 生成器调用 __next__() 方法,该方法的作用和 next() 函数完全相同(事实上,next() 函数的底层执行的也是 __next__() 方法),它会是程序继续执行,即输出“继续执行”,程序又会执行到yield i,此时 i==1,因此输出“1”,然后程序暂停。
  3. 最后,我们使用 for 循环遍历 num 生成器,之所以能这么做,是因为 for 循环底层会不断地调用 next() 函数,使暂停的程序继续执行,因此会输出后续的结果。

注意,在 Python 2.x 版本中不能使用 __next__() 方法,可以使用 next() 内置函数,另外生成器还有 next() 方法(即以 num.next() 的方式调用)。

除此之外,还可以使用 list() 函数和 tuple() 函数,直接将生成器能生成的所有值存储成列表或者元组的形式。例如: 

num = intNum()
print(list(num))

num = intNum()
print(tuple(num))

程序执行结果为:

开始执行
继续执行
继续执行
继续执行
继续执行
继续执行
[0, 1, 2, 3, 4]
开始执行
继续执行
继续执行
继续执行
继续执行
继续执行
(0, 1, 2, 3, 4)

通过输出结果可以判断出,list() 和 tuple() 底层实现和 for 循环的遍历过程是类似的。

相比迭代器,生成器最明显的优势就是节省内存空间,即它不会一次性生成所有的数据,而是什么时候需要,什么时候生成。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python生成器详解 的相关文章

随机推荐

  • 寒假小复习4

    冒泡排序 public class Sort public static void main String args double nums 1 66 73 41 30 1 double temp for int i 0 i lt nums
  • 深入springMVC

    HTML 页面中的表单最初所采用 application x www form urlencode 编码方式 并不满足文件上传的需要 所以 RFC 1867 在此基础上增加了新的 multipart form data 编码方式以支持基于表
  • LRU算法(JAVA实现)

    一 算法介绍 最近最久未使用 Least Recently Used LRU 算法是 种缓存淘汰策略 它是大部分操作系统为最大化页面命中率而广泛采用的一种页面置换算法 该算法的思路是 发生缺页中断时 将最近一段时间内最久未使用的页面置换出去
  • Java static——拾遗

    Java static 拾遗 Java Static 作为修饰符 可以用来修饰变量 方法 代码块 但绝对不能修饰类 1 修饰变量 类的所有对象共同拥有的一个属性 也称为类变量 这类似于C语言中的全局变量 类变量在类加载的时候初始化 而且只被
  • Jenkins添加用户并授权

    添加用户 先选择系统管理1 再在右侧选择2 例如 注意 之后点击保存按钮 如果没有角色先去添加角色 设置完毕一般等待几分钟才可登录查看自己的功能权限 太早登录没任何功能
  • Excel下拉框样式

    1 打开要修改的Excel 选中要修改样式的单元格 2 在上边导航栏中选择 Data 找到 Data Validation 点击下面的 Data Validation 3 在设置中找到 Allow 项 选择 List Source中填写可供
  • 运行mvn -v后出现“cmd 不是内部或外部命令,也不是可运行的程序"

    1 下载maven 官网下载地址 http maven apache org download cgi 2 解压到软件安装目录 比如我解压到E java apache maven 3 5 0 bin apache maven 3 5 0 3
  • mysql中分组取创建时间最新的数据

    近期由于公司数据库升级 遇到了一个问题 以前写的SQL语句查询结果出现了异常 sql实现的功能 将数据以PID进行分组 在组内获取创建时间最新的数据 项目数据比较敏感写了一些测试数据 执行的sql语句 select from select
  • Android中使用jiecaovideoplayer播放视频

    每天学一点2020 5 13 Android 2 Android中使用jiecaovideoplayer播放视频 1 添加依赖 2 添加运行时的权限 3 布局 4 JCVideoPlayer使用 5 设置视频 Android中使用jieca
  • moviepy使用教程

    moviepy使用教程 一 剪辑成果 二 遇到问题 三 moviepy方法分享 一 音频剪辑方法 二 视频剪辑方法 一 剪辑成果 未来 二 遇到问题 尝试使用ffmpeg moviepy pydub 其中pydub主要是对音频的处理 mov
  • @Transactional注解的方法之间调用事务是否生效及其他事务失效场景总结

    对于方法之间调用 注解 Transaction生效以及失效的场景 首先 我们需要知道 Spring是通过代理管理事务的 方法和方法之间的调用分为两种情况 解决办法可在下面列举的不同场景中自取 1 不同类之间的方法调用 如类A的方法a 调用类
  • 三、python基础——六大基本数据类型

    目录 六大标准数据类型 1 数字 Number 不可变 1 1 数值的运算 2 字符串 String 不可变 2 1 介绍 2 2 操作 2 2 1 切片 2 2 2 转义字符 3 列表 List 3 1 介绍 3 2 操作 3 2 1 索
  • 关于CyclicBarrier的一些解释

    我在网上找了一些关于CyclicBarrier的一些解释 In a nutshell just to understand key functional differences between the two public class Co
  • 华为服务器怎么修改启动项,服务器启动项设置方法

    服务器启动项设置方法 内容精选 换一换 如果密码丢失 或创建时未设置密码 推荐您在控制台设置登录密码 有以下几种现象 将制作好的SD卡插入开发者板并上电后 开发者板LED1与LED2灯状态信息异常 将制作好的SD卡插入开发者板 并通过USB
  • std::true_type和std::false_type

    一 认识std true type和std false type std true type和std false type实际上是类型别名 源码如下 template
  • @vue/cli4.5.8搭建项目的坑

    先说下我使用脚手架4 5遇到的问题 使用GUI面板配置项目 脚手架版本4 5 8 安装好Element ui 运行结果如图所示 测试了很多次 还是有问题 最终的解决方案 卸载当前脚手架版本 npm uninstall g vue cli 安
  • 开发项目curl发起https请求,cURL error 60: SSL certificate problem: unable to get local issuer cert提示找不到本地证书错误

    个人开发的时候 在新建的环境 使用curl发起https请求 基本都是错误 需要专门配置 配置完成之后 经常会跟随一个小问题 cURL error 60 SSL certificate problem unable to get local
  • Python3----Numpy总结

    Python Numpy 1 导包 import numpy as np 2 创建一个数组Array 不同于List array1 np array 1 2 3 4 5 数组当中存储相同的数据类型 不同于一般的列表 print array1
  • 面向对象设计的重要原则:SOLID

    SOLID是面向对象设计5大重要原则的首字母缩写 1 单一职责原则 SRP 2 开放封闭原则 OCP 3 里氏替换原则 LSP 4 接口隔离原则 ISP 5 依赖倒置原则 DIP 下面具体解释一下每个原则 1 单一职责原则 SRP 表明一个
  • Python生成器详解

    生成器本质上也是迭代器 不过它比较特殊 以 list 容器为例 在使用该容器迭代一组数据时 必须事先将所有数据存储到容器中 才能开始迭代 而生成器却不同 它可以实现在迭代的同时生成元素 也就是说 对于可以用某种算法推算得到的多个数据 生成器