Python迭代器
可迭代对象(Iterable)和迭代器(Iterator)的区别
可迭代对象(Iterable)
官方释义: 能够逐一返回其成员项的对象
常见的可迭代对象:
| 所有的有序类型 | 某些非序列类型 | 其他对象 |
|---|---|---|
| list | dict | 定义__iter__() |
| str | 文件对象 | 实现了Sequence语义的__getitem__()方法 |
| tuple | …… | |
| …… |
迭代器(Iterator)
官方释义: 用来表示一连串数据流的对象
常见的迭代器:
| 常见 | 其他对象 |
|---|---|
| zip | 具有__iter__()和__next__()方法 |
| map |
区别
翻看源码(Python3.7)能明显看出区别
list:
class list(object):
"""
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list.
The argument must be an iterable if specified.
"""
# 省略一大堆代码
def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass
map:
class map(object):
"""
map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from
each of the iterables. Stops when the shortest iterable is exhausted.
"""
def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass
# 省略一大堆代码
def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass
可迭代对象具有
__iter__()方法,迭代器本身是一个可迭代的对象还拥有__next__()方法。
For循环的背后
迭代器最频繁使用的场景之一就是for循环之中。
在遍历可迭代对象的时候,会为这个可迭代对象创建一个迭代器,然后执行循环体语句,直至遍历完成。
graph LR
A[需要遍历的对象] -->B{可迭代判断}
B --> |__iter__| C(创建迭代器对象)
B --> |无__iter__| D(报错: object is not iterable)
C --> E{判空}
E --> |序列为空| F(终止循环)
E --> |迭代器引发 StopIteration 异常| F(终止循环)
当一个迭代器空了后,在进行next()方法的调用会出现 StopIteration 异常,而for循环利用try...except...抓住这个错误使其能够正常运行。
优雅的判断对象是否为可迭代对象(Iterable)或迭代器(Iterator)
#引入可迭代对象和迭代器
from collections.abc import Iterable, Iterator
numList = [3, 2, 5, 1, 9, 11]
print(isinstance(numList, Iterable)) #True
print(isinstance(numList, Iterator)) #False
# 创造一个迭代器
numIterator = iter(numList)
print(isinstance(numIterator, Iterator)) #True
除了这样判断一些原有的对象,也可以自定义一个迭代器,根据前面的内容可以知道,迭代器必须拥有__iter__()和__next__()方法,再根据Python3.7的文档所述:
迭代器必须使
__iter__()方法用来返回该迭代器对象自身
# 将传入的列表的数字+10并输出
class AddTen:
def __init__(self, args_list):
self.mylist = args_list
self.endIndex = len(args_list)
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index == self.endIndex:
raise StopIteration
self.mylist[self.index] += 10
self.index += 1
return self.mylist[self.index - 1]
newAddTen = AddTen(numList)
print(isinstance(newAddTen, Iterator))
print(next(newAddTen))
print(next(newAddTen))
print(next(newAddTen))
print(next(newAddTen))
print(next(newAddTen))
print(next(newAddTen))
print(next(newAddTen))
小结
只有__iter__()是可迭代对象(Iterable),有__iter__()和__next__()的是迭代器(Iterator),根据自定义的迭代器可以看出迭代器具有Lazy Load的特性,用多少取多少方便处理超大量数据。
本文参考于 Python 3.7.12 文档
\