二十、深入 Python 迭代器和生成器
@Author: Runsen
学习python的过程中,迭代器与生成器是绕不开的话题, 什么是迭代器和生成器呢?
下面我们来了解一下什么是迭代。但在了解迭代器之前,首先需要知道什么是容器。
容器
正所谓:一切都是对象,对象的抽象就是类,而对象的集合就是容器。
容器,就是有多个对象组成的东西。
比如:列表[0,1,2]
,元组(1,2,3)
,字典{’0:'0','1':"1'}
集合{1,2,3}
都是容器。
所有的容器都是可迭代对象,也就是可以使用for循环遍历元素。
可迭代对象
所有的容器都是可迭代对象(iterable),从专业角度来讲,只要:内部含有__iter__
方法的对象,就是可迭代对象。
因此,我只要使用print('__iter__' in dir(XX))
,就能判断XX
是不是可迭代对象。
人们常说:列表、元组、字典、字符串都是可迭代对象。数字、布尔值都是不可迭代的。我一试便知。
list,dict(keys(),values(),items()),tuple,str,set,range, 文件句柄(待定)
除了print('__iter__' in dir(XX))
判断是不是可迭代对象。还是一种通过Iterable
和isinstance
方法联合使用,进行判断。
注意:list,string,tuple,dict 都属于可迭代对象,但不是迭代器
迭代器
迭代器(iterator)只是提供了一个 next
的方法。调用这个方法后,你要么得到这个可迭代对象的下一个对象,要么得到一个 StopIteration
的错误。
那么,如何声明一个可迭代对象,可以通过__iter__()
来生成可迭代对象,前提是__iter__()
传入的参数是容器。
你看下图iter(111)
是不是报错了。
因为111不能遍历,所以iter(111)直接报错。
取值
上面说过:迭代器提供了一个next
方法,调用这个方法,得到了容器的下一个对象或者一个stopiteration
的报错,具体代码如下所示。
生成器
那么什么又是生成器,和迭代器又有什么关系?
其实,生成器也是迭代器,但更加优雅。使用生成器,我们可以实现与迭代器相同的功能,但不必在类中编写iter()和next()函数
我觉得生成器就是一个迭代器的例子。,如果说迭代器是人,那么生成器就人中的一类人,比如黄人。
为什么会出来一个生成器,其实很简单声明一个迭代器很简单,但是很容易造成内存不够。生成器不会将集合中所有的元素都加载到内存。
比如下图(i for i in range(1000000000)
通过元组方式生成生成器。如果使用迭代器,那么当声明迭代器就运行不了了。
[i for i in range(1000000000] 它本是一个迭代器,但因占用的内存太大了,跑不起来,于是古人引出了生成器的概念,当你用的时候,再加载到内存空间中。
在声明生成器中,还有一种方法通过yield
关键字。
yield
和return
的区别在于yield
并没有终止函数,而return
返回值后不再执行函数内代码。
对于yield
,在scrapy用的多,然后我在其他地方没有见到过。
引用yield,带yield的函数就叫做生成器,具体示例如下所示。
今天也学到了很多东西呢,明天有什么新知识呢?真期待鸭~如果喜欢文章可以关注我哦~
本文已收录 GitHub,传送门~ ,里面更有大厂面试完整考点,欢迎 Star。
版权声明: 本文为 InfoQ 作者【刘润森】的原创文章。
原文链接:【http://xie.infoq.cn/article/d08ea5c1a41bfd8776335d93c】。未经作者许可,禁止转载。
评论