本文主要给大家分享python中可迭代对象,生成器与迭代它们到底是什么?有什么用,彼此之间的区别与联系。
一、可迭代对象
python中提供的内建类型比如列表、元组、字典和字符串等集合类型都支持迭代操作,迭代是访问集合中元素的一种方式,迭代简单点就是遍历集合中的每个元素。对于列表,元组,字符串,set数据类型来说可以直接作用于for循环的对象统称为可迭代对象(Iterable)。
字符串迭代如下图示,通过迭代我们可以访问字符串中的每一个元素。
![4180e077025bedf88d811dd7a70aec99.png](https://i-blog.csdnimg.cn/blog_migrate/6434b0e53508627b36d9bd18a2a27870.jpeg)
我们使用for循环时,只要作用于一个可迭代对象,for循环就可以正常运行,而不用太关心该对象究竟是list还是其他数据类型。
二、如何判断一个对象是不是一个可迭代对象
我们可以通过python自带的一个collections模块中的Iterable类型判断。如下例所示:
![e7f614cb2092e746448579991157b66b.png](https://i-blog.csdnimg.cn/blog_migrate/bb10626c91e9c5a1bd42b53a74c44eb8.jpeg)
三、生成器是什么
除了序列数据类型比如列表,元组和字符串可以作用于for循环外,还有生成器也可以作用于for循环。
我们用列表生成式可以快速创建一个列表,如果列表中的元素有100万,会耗费大量的内存空间。有没有一种方法在我们需要某个元素的时候在生成,这样就比较节省空间。就像我们去餐馆吃饭一样,现吃现做,如果都提前做好了就会占用很大的空间来放置。其实生成器就是这样一种东西,在你遍历到某个元素时它才会生成某个元素,它其实保存的是一种生成元素的算法。在Python中,这种一边循环一边计算的机制我们称为生成器(generator)。
创建生成器主要有两种方式:
第一种:将一个列表生成式的[]改成()
![a07a658132abdb800e22e3a8db205bfa.png](https://i-blog.csdnimg.cn/blog_migrate/9e31ca480b7ff41bd1d7da6621e255b9.jpeg)
通过上图我们发现生成器保存的是算法,如果要生成或计算下一个元素我们可以使用python中的内建函数next()获取。如下例所示:
![f9fd6e0d8c6a02f50d60512c4ae163c9.png](https://i-blog.csdnimg.cn/blog_migrate/9efd23e5641fa5d531ebabbbc387e30b.jpeg)
元素多的话使用next一个一个获取显然不现实,一般会通过使用for循环来实现,因为生成器本身就是一个可迭代对象。示例如下:
![1efac71c5de765aa05c9090f87a7a3c2.png](https://i-blog.csdnimg.cn/blog_migrate/a9430ff9a800fe1f04cabb28758b282b.jpeg)
第二种:创建生成器的方法在函数中使用yield关键字
当我们生成元素的算法如果比较复杂的时候,借助类似列表生成式这样的方式很难实现。这个时候我们可以借助函数来实现。
比如我们获取一个斐波那契数列的集合。
![c6613603033cc174ee37776d09483eab.png](https://i-blog.csdnimg.cn/blog_migrate/63af42310fc5285cff60c2fe436b395a.jpeg)
当一个函数中使用了yield关键字后,这个函数就不再是一个普通函数,而是变成一个生成器。该函数返回的是一个生成器对象。yield和return这两个关键字都是用来返回某个值,但是他们的主要区别是在函数中如果执行到return语句就会结束整个函数,而yield在返回某个值后,会在停留的位置继续向下执行,直到把整个函数体语句执行完才结束。
四.迭代器
生成器都是迭代器对象,但是列表,元组,字符串等类型虽然是可迭代对象,但它们不是迭代器,因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
把list、dict、str,tuple等可迭代对象(Iterable)变成Iterator可以使用iter()函数实现转换。
对列表直接调用next获取值就会报错,因为只有迭代器对象可以被next函数调用。
![d2f90fc6a46b717b20d0b8b41d8a90be.png](https://i-blog.csdnimg.cn/blog_migrate/2b86b7633983336f297eeaedcc75d7c3.jpeg)
通过使用iter()函数可以将可迭代对象转为迭代器。
![bde27a0031f53e23ffd7622c91f0aa9f.png](https://i-blog.csdnimg.cn/blog_migrate/32122bd4e8fd51a9017f6fa8bf5544a3.jpeg)
因此我们在执行for循环进行迭代某一个可迭代对象时,其实是等价于下图中第二个红框中的代码:
![069699295263fadecc225a3a105a1ce7.png](https://i-blog.csdnimg.cn/blog_migrate/41f82c5fef3712c919cd7e157f922a40.jpeg)
任何实现了__iter__和__next__()方法的对象都是迭代器,演示代码如下:
![5d439cc025c4c9e54ffdbf7dff2ca3ee.png](https://i-blog.csdnimg.cn/blog_migrate/bd55082b9eea16be45a75e6ebeed65ec.jpeg)
其中__iter__方法返回迭代器自身,而__next__方法返回迭代器中的下一个
![ba2bb828562b1c3106d03106c1fdd28b.png](https://i-blog.csdnimg.cn/blog_migrate/42c5e5ddfa70c4eb3c7eae636f2fd09e.jpeg)
小结:
凡是可以作用于for循环的对象都是可迭代对象。
凡是作用于next函数的对象都是迭代器。
生成器即是一个可迭代对象,又是一种特殊的迭代器,因为迭代器一般要求实现__iter__和__next__方法。
对于python中的集合类型比如列表,元组,字符串和字典它们都是可迭代对象,但是它们不是迭代器,可以通过iter函数转换为迭代器。其实可迭代对象是一个大概念;它包含生成器,序列类型(元组,字典,字符串)和迭代器。
如果你认为本文对你有价值的话,请给勇哥点个赞,你的认可是我坚持下来的最大动力。我的python专栏和爬虫专栏已经开设,有需要的话可以进行购买学习。