成为Python大牛必需要掌握的高端语法——yield

1. 什么是yield程序员

在介绍yield语法以前,首先要向你们说明Python中的迭代(iteration)、可迭代(iterable)、迭代器(iterator)以及生成器(Generator)的概念:面试

迭代是一种对数据的操做,例如针对一个list逐一获取其中的元素的过程就叫作迭代。而可迭代是对象的一种特性,迭代操做只能针对拥有可迭代特性的对象进行,常见的可迭代对象包括数组、元组、字典等数据集合,下面代码给你们演示了一个基本的迭代过程:算法

迭代器也是一种可迭代对象,与普通的可迭代对象的区别在于,迭代器内部实现了next函数用来生成每次迭代循环须要返回的元素。而最后的生成器则又是一种特殊的迭代器,具体体现上就是使用yield语法的函数,讲到这里就提到了yield语法,总的来讲yield就是用来产生一个生成器的语法,例如将上述的迭代过程修改成生成器方式能够这样写:数据库

迭代器也是一种可迭代对象,与普通的可迭代对象的区别在于,迭代器内部实现了next函数用来生成每次迭代循环须要返回的元素。而最后的生成器则又是一种特殊的迭代器,具体体现上就是使用yield语法的函数,讲到这里就提到了yield语法,总的来讲yield就是用来产生一个生成器的语法,例如将上述的迭代过程修改成生成器方式能够这样写:数组

上述代码的my_generator()即返回了一个生成器对象,每次循环时执行到yield处即返回当时的index的值,到下一次循环时将从上次返回的yield处继续执行,直到index的值不知足小于5的条件时结束整个函数,此时也结束了对这个生成器的迭代过程。函数

这四者之间的关系可能会稍微有些混乱,再给你们简单的总结一下:生成器是一种特殊的迭代器,而迭代器又是一种特殊的可迭代对象,可迭代对象就是能够执行迭代操做也就是能够经过for循环来遍历的对象。学习

本文福利:私信小编【PDF】可获取小编精心整理的电子书一套测试

2. 为何要使用yield3d

看了上述两个迭代过程,你们可能有些疑问,使用yield改形成生成器方式的代码看起来比简单的迭代一个列表的方式要复杂许多,那么这样写有什么优点呢?视频

首先,使用yield语法的生成器最主要的一个优点就是极其省内存。例如上述两个迭代过程,一样是遍历输出0-4这几个元素,使用列表的方式须要构建出一个长度为5的数组并存储在内存中,而使用生成器的方式只须要一个index变量便可实现,这仍是迭代元素较少的状况下,若是迭代的是100万甚至1000万个元素时,列表的方式就须要构建一个长度为100万或者1000万的数组,这时对于内存的使用就是很是大的负担了,而使用生成器的方式,不管是迭代100万仍是1000万个元素,依然只须要一个index变量便可实现。

而且生成器的方式是即用即计算的,即迭代到对应的元素时,这个元素才相应的计算生成出来,而列表的方式须要在迭代开始前就构建出整个迭代数组,这在某些状况下能够极大地节省计算时间。例以下面这段代码:

.在学习中有迷茫不知如何学习的朋友小编推荐一个学Python的学习q u n   227  -435-  450能够来了解一块儿进步一块儿学习!免费分享视频资料

这段代码中,实际的迭代过程只进行到第10个元素即退出了整个循环,可是在迭代开始前,依然要计算1000万次来生成迭代列表,这就形成了大量的计算和内存资源。而若是经过生成器重写该迭代过程的话:

生成器在迭代开始前并不会计算出全部须要迭代的值,只有用到时才会计算相应的值并返回,所以上述代码的index将只会计算到10即结束了整个迭代过程,避免了计算和内存资源的浪费。

3. yield语法示例1:DIY一个range函数

Python自带的range函数能够产生一个可迭代对象,经常使用于for循环中,在Python 2中range函数生成的是一个列表,而在Python 3中range函数生成的是一个生成器。如今让咱们来经过yield语法DIY一个本身的range生成器吧!

咱们首先构造一个返回给定范围数组的函数:

这个函数接受两个int类型的参数,分别为数组的开始和结束,每一个数之间间隔为1,咱们还能够经过增长一个参数来指定两个数之间的间隔,实现函数更高的灵活性:

咱们先来运行测试一下这个range函数:

上述代码的输出结果以下:

2

4

6

输出结果符合咱们的预期,如今经过yield语法来将咱们本身DIY的range函数改形成一个生成器:

改造起来也很是简单,首先将定义的用来存储迭代元素的列表删除,而后将原来添加元素到列表中的代码改形成yield start便可,这样咱们就本身DIY了一个简易的、基于生成器实现的range函数。

4. yield语法示例2:读取文件--《告白气球》

生成器除了能够用于计算生成数字元素外,在IO读取方面也能起到很大做用,例如在读取一个超大文件,或者查询某个返回结果超多的数据库时,使用经过yield语法构造的生成器来完成读取操做能够很大程度上下降程序对于内存的占用。

例如咱们有一个名为my_file.txt的文件,里面存储了周董的《告白气球》的歌词,如今咱们能够经过yield语法来构造一个生成器用于一行一行的读取每一句歌词:

这里使用with语法来读取文件,这是Python 3推荐的方式。file.readline()函数每次返回一行内容,因为返回的内容带有每行结尾的换行符,所以经过line.strip(‘ ’)将换行符过滤掉。每次经过yield返回一行内容以后,再次经过file.readline()函数获取下一行内容,直到整个文件被彻底迭代。

让咱们来运行测试一下这个按行读取文件内容的生成器:

上述代码的输出结果以下:

塞纳河畔 左岸的咖啡

我手一杯 品尝你的美

留下唇印 的嘴

……

《告白气球》的歌词就一行一行的输出到屏幕上了,因为歌词行数过多,所以这边只复制出前三行给你们演示结果。

5. yield语法示例3:斐波那契数列

斐波那契数列是一道经典的算法题,也是程序员面试时常常会被问到的一道题。斐波那契数列的就是一个形如1, 1, 2, 3, 5, 8, ……的数列,从第三项开始,每一项都等于前两项之和。使用Python来实现一个计算斐波那契数列的典型函数以下:

这个函数经过一个名为fib_list的数组存储生成的前n个斐波那契数,最后一次性返回整个数组。其中a, b = b, a + b是Python的一个特点用法,用于快速交换两个数,至关于:

参考以前DIY的range函数的写法,将这个计算斐波那契数列的函数经过yield语法修改成生成器:

让咱们来测试运行一下这个经过yield语法实现的斐波那契数列生成器:

对应的输出结果为:

1

1

2

3

5

能够看到,从第三项开始的每一项都是前两项的和,这样的输出结果就是咱们要的斐波那契数列。

相关文章
相关标签/搜索