迭代器

什么是可迭代对象?

我们知道list、tuple、dict、set、

str 可以用for循环遍历,这种遍历称为迭代(Iteration),被遍历的list或tuple等被称为可迭代对象。

什么是迭代器( Iterator)

迭代器是一个具有迭代功能的对象,它从集合的第一个元素开始访问,直到所有的元素被遍历完,它有两个基本的方法iter()和next()。其中iter()用来创建迭代器对象,next()用于遍历对象的元素。

迭代器提供了一种不依赖索引取值的方式,适用于遍历元素比较多的集合,不会在内存中再占用一大块内存,而是随着循环每次生成一个,从而节省内存占用。

集合数据类型如 list 、 dict 、 str 等是可迭代的, 但不是迭代器 ,不过可以通过 iter() 函数获得一个 Iterator 对象。

#迭代器=iter(容器)
list01 = [1, 2, 3, 4, 5]
iterator = iter(list01)

在遍历字符串,列表或元组对象时经常会用到迭代器,使用next(),获取其中的所有语法。

next()函数不断返回下一个数据,直到没有数据时抛出StopIteration错误。

list02=[1,2,3]
it=iter(list02)
while True:
print(next(it))

#输出结果
1
2
3
Traceback(most recent call last):
File"func_1.py", line 55, in<module>
print(next(it))
StopIteration

可以使用isinstance()判断一个对象是否可迭代:

from collections.abc import Iterable
print(isinstance([1, 2, 3], Iterable))  # 输出True

自定义迭代器

自定义迭代器,需要再实现两个方法 iter() 与 next() 。

iter()方法返回迭代器对象本身,next()方法返回下一个元素。for语句就是通过__iter__()方法来获得迭代器对象,接着不停的调用迭代器对象的__next__()方法,循环遍历取值。

生成器

生成器是一个函数,普通函数用 return 返回一个值,如果一个函数用yield返回值,就叫生成器函数。函数被调用时会返回一个生成器对象。这个生成器对象自动实现了__iter__() 与 next() ,生成器是一种特殊的迭代器。

生成器函数和普通函数的区别:

普通函数遇到return语句或者最后一行语句就返回。而变成生成器函数,调用的时候返回的是生成器对象。在每次调用next()或用for语句进行下一次迭代时才执行,遇到yield语句停止,再次执行时从停止的地方继续执行,直到遇到下一个yield语句。

def func(n):
    for i in range(n):
        yield i

#调用该函数
func(5)
<generatorobjectfuncat 0x000001E76A903B48>    #返回的是生成器对象
#查看该对象中包含的方法
print(dir(func(5)))
['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']

f=func(5)
print(next(f))    #0
print(next(f))    #1

使用生成器的好处

假设创建了一个包含1000个元素的列表,这1000个元素都放在内存中会占用很大的存储空间。而生成器并不是一上来就把所有值加载进内存,而是你要用几个元素,它才会把这些元素一个个读出来,大大节约了内存。

生成器表达式

有一种非常简便的方式创建生成器,就是生成器表达式。

生成器= (操作 for 元素 in 可迭代对象 )

list03=(x*2 for x in range(5)) #生成列表

for i in list03:
    print(i) #输出0 2 4 6 8