人生苦短,我选Python

前文传送门

小白学 Python(1):开篇

小白学 Python(2):基础数据类型(上)

小白学 Python(3):基础数据类型(下)

小白学 Python(4):变量基础操作

小白学 Python(5):基础运算符(上)

小白学 Python(6):基础运算符(下)

小白学 Python(7):基础流程控制(上)

小白学 Python(8):基础流程控制(下)

小白学 Python(9):基础数据结构(列表)(上)

小白学 Python(10):基础数据结构(列表)(下)

小白学 Python(11):基础数据结构(元组)

小白学 Python(12):基础数据结构(字典)(上)

小白学 Python(13):基础数据结构(字典)(下)

小白学 Python(14):基础数据结构(集合)(上)

小白学 Python(15):基础数据结构(集合)(下)

小白学 Python(16):基础数据类型(函数)(上)

小白学 Python(17):基础数据类型(函数)(下)

小白学 Python(18):基础文件操作

小白学 Python(18):基础文件操作

小白学 Python(19):基础异常处理

小白学 Python(20):迭代器基础

生成器

我们前面聊过了为什么要使用迭代器,各位同学应该还有印象吧(说没有的就太过分了)。

列表太大的话会占用过大的内存,可以使用迭代器,只拿出需要使用的部分。

生成器的设计原则和迭代器是相似的,如果需要一个非常大的集合,不会将元素全部都放在这个集合中,而是将元素保存成生成器的状态,每次迭代的时候返回一个值。

比如我们要生成一个列表,可以采用如下方式:

list1 = [x*x for x in range(10)]
print(list1)

结果如下:

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

如果我们生成的列表非常的巨大,比如:

list2 = [x*x for x in range(1000000000000000000000000)]

结果如下:

Traceback (most recent call last):
File "D:/Development/Projects/python-learning/base-generator/Demo.py", line 3, in <module>
list2 = [x*x for x in range(1000000000000000000000000)]
File "D:/Development/Projects/python-learning/base-generator/Demo.py", line 3, in <listcomp>
list2 = [x*x for x in range(1000000000000000000000000)]
MemoryError

报错了,报错信息提示我们存储异常,并且整个程序运行了相当长一段时间。友情提醒,这么大的列表创建请慎重,如果电脑配置不够很有可能会将电脑卡死。

如果我们使用生成器就会非常方便了,而且执行速度嗖嗖的。

generator1 = (x*x for x in range(1000000000000000000000000))
print(generator1)
print(type(generator1))

结果如下:

<generator object <genexpr> at 0x0000014383E85B48>
<class 'generator'>

那么,我们使用了生成器以后,怎么读取生成器生成的数据呢?

当然是和之前的迭代器一样的拉,使用 next() 函数:

generator2 = (x*x for x in range(3))
print(next(generator2))
print(next(generator2))
print(next(generator2))
print(next(generator2))

结果如下:

Traceback (most recent call last):
File "D:/Development/Projects/python-learning/base-generator/Demo.py", line 14, in <module>
print(next(generator2))
StopIteration

直到最后,抛出 StopIteration 异常。

但是,这种使用方法我们并不知道什么时候会迭代结束,所以我们可以使用 for 循环来获取每生成器生成的具体的元素,并且使用 for 循环同时也无需关心最后的 StopIteration 异常。

generator3 = (x*x for x in range(5))
for index in generator3:
print(index)

结果如下:

0
1
4
9
16

generator 非常的强大,本质上, generator 并不会取存储我们的具体元素,它存储是推算的算法,通过算法来推算出下一个值。

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

比如我们定义一个函数,emmmmmm,还是简单点吧,大家领会精神:

def print_a(max):
i = 0
while i < max:
i += 1
yield i a = print_a(10)
print(a)
print(type(a))

结果如下:

<generator object print_a at 0x00000278C6AA5CC8>
<class 'generator'>

这里使用到了关键字 yieldyieldreturn 非常的相似,都可以返回值,但是不同的是 yield 不会结束函数。

我们调用几次这个用函数创建的生成器:

print(next(a))
print(next(a))
print(next(a))
print(next(a))

结果如下:

1
2
3
4

可以看到,当我们使用 next() 对生成器进行一次操作的时候,会返回一次循环的值,在 yield 这里结束本次的运行。但是在下一次执行 next() 的时候,会接着上次的断点接着运行。直到下一个 yield ,并且不停的循环往复,直到运行至生成器的最后。

还有一种与 next() 等价的方式,直接看示例代码吧:

print(a.__next__())
print(a.__next__())

结果如下:

5
6

接下来要介绍的这个方法就更厉害了,不仅能迭代,还能给函数再传一个值回去:

def print_b(max):
i = 0
while i < max:
i += 1
args = yield i
print('传入参数为:' + args) b = print_b(20)
print(next(b))
print(b.send('Python'))

结果如下:

1
传入参数为:Python
2

上面讲了这么多,可能各位还没想到生成器能有什么具体的作用吧,这里我来提一个——协程。

在介绍什么是协程之前先介绍下什么是多线程,就是在同一个时间内可以执行多个程序,简单理解就是你平时可能很经常的一边玩手机一边听音乐(毫无违和感)。

协程更贴切的解释是流水线,比如某件事情必须 A 先做一步, B 再做一步,并且这两件事情看起来要是同时进行的。

def print_c():
while True:
print('执行 A ')
yield None
def print_d():
while True:
print('执行 B ')
yield None c = print_c()
d = print_d()
while True:
c.__next__()
d.__next__()

结果如下:

...
执行 A
执行 B
执行 A
执行 B
执行 A
执行 B
执行 A
执行 B
执行 A
执行 B
...

因为 while 条件设置的是永真,所以这个循环是不会停下来的。

这里我们定义了两个生成器,并且在一个循环中往复的调用这两个生成器,这样看起来就是两个任务在同时执行。

最后的协程可能理解起来稍有难度,有问题可以在公众号后台问我哦~~~

示例代码

本系列的所有代码小编都会放在代码管理仓库 Github 和 Gitee 上,方便大家取用。

示例代码-Github

示例代码-Gitee

小白学 Python(21):生成器基础的更多相关文章

  1. 小白学 Python(23):Excel 基础操作(上)

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...

  2. 小白学 Python(24):Excel 基础操作(下)

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...

  3. 小白学 Python 爬虫(21):解析库 Beautiful Soup(上)

    小白学 Python 爬虫(21):解析库 Beautiful Soup(上) 人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前 ...

  4. 小白学 Python(5):基础运算符(上)

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...

  5. 小白学 Python 爬虫(30):代理基础

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  6. 小白学 Python 爬虫(32):异步请求库 AIOHTTP 基础入门

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  7. 小白学 Python 爬虫(33):爬虫框架 Scrapy 入门基础(一)

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  8. 小白学 Python 爬虫(34):爬虫框架 Scrapy 入门基础(二)

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  9. 小白学 Python 爬虫(35):爬虫框架 Scrapy 入门基础(三) Selector 选择器

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

随机推荐

  1. 1.Eclipse下载、常用配置、快捷键

    Eclipse官网下载:https://www.eclipse.org/downloads/packages/ 自动补全 位置:Eclipse——Window——Perferences——Java—— ...

  2. Fiddler的基本使用

    目录 清空历史请求 请求所消耗的时间 发送的数据在 设置fiddler过滤请求 模拟弱网环境 Ctrl+R 拦截数据,拦截数据又称"打断点" fiddler开启的时候就是默认开始抓 ...

  3. sql事务的使用及其技巧整理

    sql事务的使用及其技巧整理 概述: 在实际项目开发中,为了确保数据操作结果的一致性等要求,事务是一个必不可少的解决利器. 根据SQLSERVER实现原理,其实,SQLSERVER的每一条执行语句都是 ...

  4. Python开发【第六篇】循环语句

    while 语句 注意事项:1.要控制循环的真值表达式的值来防止死循环 ​ 2.通常用真值表达式内的循环变量来控制循环条件 ​ 3.通常在语句内部改变循环变量 ​ 4.只要是语句都可以互相嵌套 whi ...

  5. (21)ASP.NET Core EF创建模型(关系)

    1.关系 关系定义两个实体之间的关系.在关系型数据库中,这由外键约束表示. 2.术语定义 有许多术语用于描述关系:●相关实体:这是包含外键属性的实体.有时称为关系的"子级".●主体 ...

  6. 剑指Offer(十九)——顺时针打印矩阵

    题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字. 例如,如果输入如下4 X 4矩阵: 1   2    3     4 5   6    7     8 9   10  11  ...

  7. postman使用实例

    以下以一个登录接口为例,介绍一下postman是如何发请求的. 先执行Pre-request Scripts(预处理) - body - tests(进行断言) postman中变量的引用: {{}}

  8. .Net Core3.0 配置Configuration

    准备 .NET core和.NET项目配置上有了很大的改变,支持的也更加丰富了比如命令行,环境变量,内存中.NET对象,设置文件等等..NET项目我们常常把配置信息放到webConfig 或者appC ...

  9. 玩转OneNET物联网平台之HTTP服务① —— 模拟上传温度(TcpClient)

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  10. 图论-最短路径<Dijkstra,Floyd>

    昨天: 图论-概念与记录图的方法 以上是昨天的Blog,有需要者请先阅读完以上再阅读今天的Blog. 可能今天的有点乱,好好理理,认真看完相信你会懂得 分割线 第二天 引子:昨天我们简单讲了讲图的概念 ...