python学习之【第十三篇】:Python中的生成器
1.为什么要有生成器?
在Python中,通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。那么此时聪明的你肯定会这么想:有没有一种机制,当我们想要创建列表时,不要直接先把列表中元素全部创建出来,而是把列表元素生成的方法给我,当我要使用哪几个元素的时候我再生成,现做现卖,用多少做多少,这样多好。其实,这些前人们早就替我们想到了,所以,生成器应运而生。
2.什么是生成器?
如果列表元素可以按照某种算法推算出来,这样我们就不必创建出完整的列表,而是在循环的过程中不断推算出后续的元素,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器generator。
3.如何创建生成器?
要创建一个生成器generator,有很多种方法。我们介绍两种常用的方法:
- 简单生成器。第一种方法很简单,只要把一个列表生成式的
[]改成(),就创建了一个生成器generator; - 生成器函数。如果推算的算法比较复杂,用类似列表生成式无法实现的时候,还可以用函数来实现,这就是生成器函数。
4. 生成器表达式
只要把一个列表生成式的[ ]改成( ),就创建了一个生成器表达式generator。

创建L和g的区别仅在于最外层的[ ]和( ),L是一个list,而g是一个generator。
我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
因为generator也是可迭代对象,所以可以使用for循环来迭代:

我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
5. 生成器函数
在上述的简单生成器中,元素推算的算法仅仅是x*x,比较简单。但是如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,我们可以用函数来实现。这个定义元素推算算法的函数我们称之为生成器函数。
生成器函数与普通函数有一个很重要的区别,那就是:生成器函数中需要return的地方通通使用yield来替换。
yield关键字
yield关键字,其作用和return的功能差不多,就是返回一个值给调用者,只不过有yield的函数返回值后函数依然保持调用yield时的状态,当下次调用的时候,在原先的基础上继续执行代码,直到遇到下一个yield或者满足结束条件结束函数为止。
我们可以看以下例子:

首先定义一个生成器函数,调用该生成器函数时,返回一个生成器对象generator,然后用next()函数不断获得下一个返回值,在执行过程中,遇到yield就中断,下次又继续执行。执行3次yield后,已经没有yield可以执行了,所以,第4次调用next(g)就报错。
同样的,使用生成器函数,我们基本上也不会用next()来获取下一个返回值,而是直接使用for循环来迭代:
def test():
print('step1')
yield 1
print('step2')
yield 2
print('step3')
yield 3
g = test()
for i in g:
print(i)
# 输出
# step1
# 1
# step2
# 2
# step3
# 3
6.生成器函数与普通函数的区别
生成器函数与普通函数主要有以下不同:
- 生成器函数包含一个或者多个
yield; - 当调用生成器函数时,函数将返回一个对象,但是不会立刻向下执行;
- 像
__iter__()和__next__()方法等是自动实现的,所以我们可以通过next()方法对对象进行迭代; - 一旦函数被
yield,函数会暂停,控制权返回调用者; - 局部变量和它们的状态会被保存,直到下一次调用;
- 函数终止的时候,
StopIteraion会被自动抛出;
7.应用
咋一看,生成器好像没有什么用啊,其实不然,很多情况下元素是无穷无尽的,例如斐波那契数列,杨辉三角等,这些元素都是不能被穷举的,所以我们无法将所有元素都放到一个列表里,只能是保存元素推算的算法,再进行逐个推算,这就是生成器的好处。
例如生成杨辉三角的代码,把每一行看做一个list,试写一个generator,不断输出下一行的list:
1
/ \
1 1
/ \ / \
1 2 1
/ \ / \ / \
1 3 3 1
/ \ / \ / \ / \
1 4 6 4 1
/ \ / \ / \ / \ / \
1 5 10 10 5 1
# 杨辉三角
def triangles():
old_list = []
new_list = []
while True:
length = len(old_list)
if length == 0:
new_list.append(1)
else:
for item in range(length + 1):
if item == 0:
new_list.append(1)
elif item == length:
new_list.append(1)
else:
tmp = old_list[item - 1] + old_list[item]
new_list.append(tmp)
yield new_list
old_list = new_list.copy()
new_list.clear()

(完)
python学习之【第十三篇】:Python中的生成器的更多相关文章
- Python 学习笔记(十三)Python函数(二)
参数和变量 >>> def foo(a,b): #函数是一个对象 return a+b >>> p =foo #对象赋值语句.将foo函数赋值给p这个变量 > ...
- Python 学习笔记(十三)Python函数(一)
函数基础 函数:函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.Python提供了许多内建函数,比如print().可以自己创建函数,这 ...
- Python开发【第二十三篇】:持续更新中...
Python开发[第二十三篇]:持续更新中...
- Python学习笔记(十三)
Python学习笔记(十三): 模块 包 if name == main 软件目录结构规范 作业-ATM+购物商城程序 1. 模块 1. 模块导入方法 import 语句 import module1 ...
- Python学习笔记之基础篇(-)python介绍与安装
Python学习笔记之基础篇(-)初识python Python的理念:崇尚优美.清晰.简单,是一个优秀并广泛使用的语言. python的历史: 1989年,为了打发圣诞节假期,作者Guido开始写P ...
- Python开发【第十三篇】:jQuery--无内容点击-不进去(一)
Python开发[第十三篇]:jQuery--无内容点击-不进去(一)
- openresty 学习笔记番外篇:python的一些扩展库
openresty 学习笔记番外篇:python的一些扩展库 要写一个可以使用的python程序还需要比如日志输出,读取配置文件,作为守护进程运行等 读取配置文件 使用自带的ConfigParser模 ...
- openresty 学习笔记番外篇:python访问RabbitMQ消息队列
openresty 学习笔记番外篇:python访问RabbitMQ消息队列 python使用pika扩展库操作RabbitMQ的流程梳理. 客户端连接到消息队列服务器,打开一个channel. 客户 ...
- Python学习系列(四)Python 入门语法规则2
Python学习系列(四)Python 入门语法规则2 2017-4-3 09:18:04 编码和解码 Unicode.gbk,utf8之间的关系 2.对于py2.7, 如果utf8>gbk, ...
- Python学习入门基础教程(learning Python)--5.6 Python读文件操作高级
前文5.2节和5.4节分别就Python下读文件操作做了基础性讲述和提升性介绍,但是仍有些问题,比如在5.4节里涉及到一个多次读文件的问题,实际上我们还没有完全阐述完毕,下面这个图片的问题在哪呢? 问 ...
随机推荐
- 大神都在用的yum源
本文原创首发于公众号:编程三分钟 yum 命令的使用 yum命令天天都在用,都快用烂了,但是很多人不知道为什么只要联网,yum命令就能像老奶奶手中的魔法棒一样,随心所欲的下载到想到的包. 比如你想装个 ...
- 最简单的JS实现json转csv
工作久了,总会遇到各种各样的数据处理工作,比如同步数据,初始化一些数据,目前比较流行的交互数据格式就是JSON,可是服务器中得到的JSON数据如果提供给业务人员看的话可能会非常不方便,这时候,转成CS ...
- 理解numpy.dot()
import numpy.matlib import numpy as np a = np.array([[1,2],[3,4]]) b = np.array([[11,12],[13,14]]) p ...
- ZGC介绍
zgc是一款可拓展的低时延,为实现以下几个目标而诞生的垃圾回收器: 停顿时间不超过10ms 停顿时间不会导致堆大小增长 堆大小范围可支持几G到几T 再看一下zgc的标签: region-based ( ...
- python 中的一点新知识
逻辑行与物理行 所谓物理行(Physical Line)是你在编写程序时 你所看到 的内容.所谓逻辑行(Logical Line)是 Python 所看到 的单个语句.Python 会假定每一 物理行 ...
- 关于vue使用的一些小经验
这一年来说,vue的势头很猛,用户量“噌”“噌”“噌”的涨 为了不掉队不落伍.在后台大哥的胁迫下,不得不选择用了它 刚开始很难接受vue的写法,在编辑器里很容易报错,基本上每行都会出现红色的波浪线 这 ...
- NodeJs编写Cli实现自动初始化新项目目录结构
应用场景 前端日常开发中,会遇见各种各样的cli,这些工具极大地方便了我们的日常工作,让计算机自己去干繁琐的工作,而我们,就可以节省出大量的时间用于学习.交流.开发. 注释:文章附有源码链接! 使用工 ...
- spark版本定制课程-第1课
spark版本定制课程-第1课 1.学习本课程可以自己动手改进spark,或者给spark增加功能.增加某些官方没有提供的功能,通过本课程希望早就一些顶级spark专家,根据整个社会的需要对spark ...
- mysql 主从关系ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
连接 amoeba-mysql出现Could not create a validated object, cause: ValidateObject failed mysql> start s ...
- 数据类型(二)---day04
目录 上节课回顾 五 变量 (一)什么是变量 (二)变量的组成 (三)变量名的命名规范 (四)常量 (五)python变量内存管理 (六)变量的三种打印方式 六 数据类型 (一)数字类型 (二)字符串 ...