先用一个关系图来表示他们之间的关系:
基础概念:
可迭代对象
定义:可迭代对象:能够用于for循环的python对象
可迭代对象实现了__iter__方法,该方法返回的是当前对象的迭代器类的实例,可以使用
if '__iter__' in dir(str)来判断对象是否有实现了__iter__方法,可迭代对象实现了可迭代协议:实现__iter__方法
from collections import Iterable,Iterator
class MyIterator:
def __iter__(self):
pass
k = MyIterator()
print(isinstance(k,Iterable)) 返回True
迭代器
定义:迭代器:可以被next()函数调用并不断返回下一个值的对象称为迭代器。迭代器原则上只需要实现__next__方法即可,但是python规定迭代器本身必须也是可迭代的,所以必须实现__iter__()方法
迭代器必须实现必须实现__iter__和__next__()方法(python2中是next()方法),
迭代器实现了迭代器协议:(1)实现__iter__方法,返回一个迭代器对象实例。(2)实现__next__()方法返回下一个生成值
class MyListIterator(object): # 定义迭代器类,其是MyList可迭代对象的迭代器类
def __init__(self, data):
self.data = data # 上边界
self.now = 0 # 当前迭代值,初始为0
def __iter__(self):
return self # 返回该对象的迭代器类的实例;因为自己就是迭代器,所以返回self
def __next__(self): # 迭代器类必须实现的方法
# pass
while self.now < self.data:
self.now += 1
return self.now - 1 # 返回当前迭代值
raise StopIteration # 超出上边界,抛出异常
my = MyListIterator(10)
print(isinstance(my,Iterable),"44444444444444444")
print(isinstance(my,Iterator),"44444444444444444")
生成器
python中一边循环,一边计算的机制叫做生成器
生成器两种生成方式:(1)类似列表生成式:将列表生成式的[]换成()
(2)使用yield关键字返回结果的函数
生成器是特殊的迭代器,其特殊之处在于自动实现了迭代器协议,不需要手动实现两个方法,使用yield关键字返回值,可以使用send方法修改当前迭代值,而普通迭代器需要手动实现,不能修改当前迭代值。
有些文档中说迭代器,是将所有的值都生成存放在内存中,而生成器
则是需要元素才临时生成,节省时间,节省空间。
这个结论是错误的,因为迭代器也是需要元素临时生成,这个跟生成器是一致的,实验如下:
from collections import Iterator
from sys import getsizeof
a = [i for i in range(1001)]
print(type(a))
print(getsizeof(a))#4516
b = iter(a)
print(type(b))
print(isinstance(b,Iterator))
print(getsizeof(b))#32
c = (i for i in range(1001))
print(getsizeof(b)) #32
迭代器,生成器遍历完一次就不能从头开始了
a = iter([x for x in range(10)])
for i in a:
print(i)
print("a第一次遍历完毕")
b= (x for x in range(10))
for i in b:
print(i)
print("b第一次遍历完毕")
for i in a:
print(i)
print("a第2次遍历完毕")
for i in b:
print(i)
print("第2次遍历完毕")
从以下结果可以看出没有执行第二次for循环
0
1
2
3
4
5
6
7
8
9
a第一次遍历完毕
0
1
2
3
4
5
6
7
8
9
b第一次遍历完毕
a第2次遍历完毕
第2次遍历完毕
a = iter([x for x in range(10)])
print(3 in a)
print(3 in a)
这个例子也能说明
True
False
可迭代对象,生成器转换成迭代器iter()函数
通过python内置的 iter()方法可以将可迭代对象,生成器转换成为迭代器
iter()函数原理是创建一个可迭代对象或生成器的迭代器类实例,并将它返回
next()方法
next()方法用于调用迭代器或生成器的__next__()方法,返回下一个值
for循环实现原理
在循环遍历自定义容器对象时,会使用python内置函数iter()调用遍历对象的_iter_(self)获得一个迭代器,之后再循环对这个迭代器使用next()调用迭代器对象的_next_(self)。
注意点:_iter_(self)只会被调用一次,而_next_(self)会被调用 n 次,直到出现StopIteration异常。
for item in Iterable 循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束
总结
凡是可作用于 for 循环的对象都是 Iterable 类型;
凡是可作用于 next() 函数的对象都是 Iterator 类型
集合数据类型如 list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可
以通过 iter() 函数获得用个 Iterator 对象。