1.为什么要有生成器?

在Python中,通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。那么此时聪明的你肯定会这么想:有没有一种机制,当我们想要创建列表时,不要直接先把列表中元素全部创建出来,而是把列表元素生成的方法给我,当我要使用哪几个元素的时候我再生成,现做现卖,用多少做多少,这样多好。其实,这些前人们早就替我们想到了,所以,生成器应运而生。

2.什么是生成器?

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

3.如何创建生成器?

要创建一个生成器generator,有很多种方法。我们介绍两种常用的方法:

  1. 简单生成器。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个生成器generator
  2. 生成器函数。如果推算的算法比较复杂,用类似列表生成式无法实现的时候,还可以用函数来实现,这就是生成器函数。

4. 生成器表达式

只要把一个列表生成式的[ ]改成( ),就创建了一个生成器表达式generator

创建Lg的区别仅在于最外层的[ ]( )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中的生成器的更多相关文章

  1. Python 学习笔记(十三)Python函数(二)

    参数和变量 >>> def foo(a,b): #函数是一个对象 return a+b >>> p =foo #对象赋值语句.将foo函数赋值给p这个变量 > ...

  2. Python 学习笔记(十三)Python函数(一)

    函数基础 函数:函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.Python提供了许多内建函数,比如print().可以自己创建函数,这 ...

  3. Python开发【第二十三篇】:持续更新中...

    Python开发[第二十三篇]:持续更新中...

  4. Python学习笔记(十三)

    Python学习笔记(十三): 模块 包 if name == main 软件目录结构规范 作业-ATM+购物商城程序 1. 模块 1. 模块导入方法 import 语句 import module1 ...

  5. Python学习笔记之基础篇(-)python介绍与安装

    Python学习笔记之基础篇(-)初识python Python的理念:崇尚优美.清晰.简单,是一个优秀并广泛使用的语言. python的历史: 1989年,为了打发圣诞节假期,作者Guido开始写P ...

  6. Python开发【第十三篇】:jQuery--无内容点击-不进去(一)

    Python开发[第十三篇]:jQuery--无内容点击-不进去(一)

  7. openresty 学习笔记番外篇:python的一些扩展库

    openresty 学习笔记番外篇:python的一些扩展库 要写一个可以使用的python程序还需要比如日志输出,读取配置文件,作为守护进程运行等 读取配置文件 使用自带的ConfigParser模 ...

  8. openresty 学习笔记番外篇:python访问RabbitMQ消息队列

    openresty 学习笔记番外篇:python访问RabbitMQ消息队列 python使用pika扩展库操作RabbitMQ的流程梳理. 客户端连接到消息队列服务器,打开一个channel. 客户 ...

  9. Python学习系列(四)Python 入门语法规则2

    Python学习系列(四)Python 入门语法规则2 2017-4-3 09:18:04 编码和解码 Unicode.gbk,utf8之间的关系 2.对于py2.7, 如果utf8>gbk, ...

  10. Python学习入门基础教程(learning Python)--5.6 Python读文件操作高级

    前文5.2节和5.4节分别就Python下读文件操作做了基础性讲述和提升性介绍,但是仍有些问题,比如在5.4节里涉及到一个多次读文件的问题,实际上我们还没有完全阐述完毕,下面这个图片的问题在哪呢? 问 ...

随机推荐

  1. 前端之CSS基础及使用方法

    CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). CSS语法 CSS实例 ...

  2. 基于Influxdb对InfluxDBResultMapper的一点扩展

    理想很饱满,现实很骨感. 由于业务需要"灵活可配置"的功能需求,在使用java开发Influxdb查询功能的时候,遇到了一个问题,Measurement注解的名称有可能需要动态变化 ...

  3. abp(net core)+easyui+efcore实现仓储管理系统——EasyUI之货物管理五 (二十三)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  4. 从实践角度重新理解BIO和NIO

    前言 这段时间自己在看一些Java中BIO和NIO之类的东西,看了很多博客,发现各种关于NIO的概念说的天花乱坠头头是道,可以说是非常的完整,但是整个看下来之后,自己对NIO还是一知半解的状态,所以这 ...

  5. hydra暴力破解

    hydra,是一个非常好用的暴力破解工具,而且名字也很cool. 下面是官网上的介绍: AFP, Cisco AAA, Cisco auth, Cisco enable, CVS, Firebird, ...

  6. 实验吧之【who are you?】(时间盲注)补充

    第二种方法 使用brup进行盲注  也是一个道理 不多贴了 这里提一下  burp怎么判断超时 Options->Connections->Tiimeouts->Normal这一空 ...

  7. [Luogu3932] 浮游大陆的68号岛

    题目背景 大样例下发链接: https://pan.baidu.com/s/1nuVpRS1 密码: sfxg 浮游大陆的68号岛,位于浮游大陆的边境地带.平时很少有人造访. 岛上被浓厚的森林覆盖. ...

  8. [Luogu2455] [SDOI2006]线性方程组

    题目描述 已知n元线性一次方程组. 其中:n<=50, 系数是[b][color=red]整数<=100(有负数),bi的值都是整数且<300(有负数)(特别感谢U14968 mmq ...

  9. 简单理解TCP通信的三次握手

    TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接. 位码(可以理解为请求状态): 有6种标示:SYN(synchronous建立联机) ACK(acknowledg ...

  10. Rancher与ARM深化战略合作,“软硬结合”加速边缘计算时代

    时至今日,许多企业已将边缘计算列为战略目标,对于部分企业而言,边缘计算则已成为它们势在必行的部分.而随着对应用软件和硬件能力的需求不断增长,容器和Kubernetes已发展为边缘计算领域备受瞩目的一项 ...