欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

玩转可迭代对象、迭代器与生成器:你需要知道的一切

最编程 2024-01-13 21:15:56
...

生成器

《流畅的Python》

容器序列:list, tuple, collections.deque这些序列能存放不同类型的数据。

在Python中,所有容器都是可迭代对象。

 

 

 

 可迭代对象:

1,对象实现了能返回迭代器的__iter__方法,那么对象就是可迭代的。

2,序列都可以迭代。

3,实现了__getitem__方法,而且接受从0开始的索引,这种对象也可以迭代。

 

可迭代对象与迭代器之间的关系:Python从可迭代对象中获取迭代器。 

 

 

 

 

迭代

 通过for循环遍历list或tuple,这种遍历我们称为迭代(Iteration)。

 enumerate( )函数:

可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身

from collections import Iterable

小结

任何可迭代对象都可以作用于for循环,包括我们自定义的数据类型,只要符合迭代条件,就可以使用for循环。 

 

 

列表生成式

在一个列表/字典/集合/元组生成式中,放在for前面的if……else是表达式,而放在for后面的if是过滤条件,不能带else。

 

 

 

生成器

如果列表元素可以按照某种算法推算出来,那我们因此可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。

在Python中,这种一边循环一边计算的机制,称为生成器:generator。

generator保存的是算法,每次调用next( g ),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

 创建生成器的2种方式:

1,把列表生成式中的中括号[ ] 改成小括号( )

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

执行流程:

最难理解的就是generator和函数的执行流程不一样。

函数:是顺序执行,遇到return语句或者最后一行函数语句就返回。

而变成generator的函数,在每次调用next( )的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

生成器拿不到return语句的返回值

用for循环调用generator时拿不到return语句的返回值。

如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中。

 

 

 

迭代器

迭代器的方法有iter()和next(),本质是实现了__iter__()和__next__()方法,只要任何对象实现了这两个方法,那该对象就是一个迭代器。

把一个类作为一个迭代器使用,需要在类中实现两个方法 __iter__() 与 __next__() 。

可迭代对象Iterable:凡是可作用于for循环的对象都是Iterable类型,即都是可迭代对象。

迭代器Iterator:凡是可作用于next()函数并不断返回下一个值的对象都是Iterator类型,即都是迭代器,它们表示一个惰性计算的序列;

 PS,  注意迭代器Iterator和生成器generator的区别

1,可迭代对象Iterable

可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如list, tuple,  dict, set,  str等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

2,isinstance()函数:

判断一个对象是否是Iterable对象、Iterator对象

#可迭代对象
from collections import Iterable


#迭代器
from collections import Iterator

3,iter( )函数:

把集合数据类型listdictstrIterable变成Iterator.

4,问题:为什么listdictstr等数据类型不是Iterator

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。

可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据;

所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

小结

Python的for循环本质上就是通过不断调用next()函数实现的,而且for循环会处理stopIteration异常。

for i in [1,2,3,4,5]:
    pass

#for循环等价于下面的函数:

#首先获得Iterator对象
it=iter([1,2,3,4,5])
#循环
while True:
    try:
        #获得下一个值
        print(next(it))
    except StopIteration:
        #遇到StopIteration就退出循环
        break

 

推荐阅读