首先要说明的几个概念
1 什么是可迭代对象(Iterable)
>>> s = 'hello'
>>> for i in s:
print(i)
h
e
l
l
o
>>> from collections.abc import Iterable,Iterator
>>> print(isinstance(s,Iterable))
True
总结:凡是可作用于for循环的对象都是可迭代对象,它们都是Iterable类型的对象,例如string,list,tuple,dict等类型
2 什么是迭代器(Iterator)
可迭代对象就是迭代器吗?
>>> s = 'hello'
>>> print(isinstance(s,Iterator))
False
>>>
显然不一定,例如string,list就不是,那什么是迭代器呢?
迭代器(Iterator)是指可以被next函数调用并不断返回下一个值的对象。
如何获取一个迭代器?
>>> s = 'hello'
>>> iter = iter(s)
>>> print(isinstance(iter,Iterator))
True
>>> for i in iter:
print(i)
h
e
l
l
o
>>>
通过将一个可迭代对象(Iterable)传入iter函数可返回一个迭代器(Iterator).
自定义迭代器
>>> class Av(object):
def __init__(self,list):
self.list = list
def __next__(self):
if len(self.list):
return self.list.pop(0)
else:
raise StopIteration
def __iter__(self):
return self
>>> av = Av([1,2,3,4,5])
>>> print(isinstance(av,Iterable))
True
>>> print(isinstance(av,Iterator))
True
>>> for i in av:
print(i)
1
2
3
4
5
>>>
通过以上代码我们不难看出
Iterator是Iterable的子类
当类实现了__iter__函数则该类是Iterable(可迭代)类型
当Iterable类实现了__next__函数则该类是Iterator(生成器)类型
3 生成器generator
生成器是一种特殊的迭代器,当在函数中添加yield语句后,调用该函数会返回一个generator对象
>>> def gen():
for i in range(10):
yield i**2
>>> print(type(gen))
<class 'function'>
>>> g = gen()
>>> print(type(g))
<class 'generator'>
>>> for i in g:
print(i)
0
1
4
9
16
25
36
49
64
81
>>> g2 = gen()
>>> for i in g2:
print(i)
0
1
4
9
16
25
36
49
64
81
>>>
一个生成器对象遍历一次后会失效,原因是迭代器是不可逆的。
当for循环作用于生成器对象时,会执行函数内部的代码直到遇到yield语句为止并返回yield后的值,然后将函数程序挂起保存执行现场等待下一次遍历直到遇到return语句或执行完函数的最后一句代码。
生成器对象还可以通过__next__函数来不断返回下一个值来进行遍历,直到抛出StopItIteration异常。
>>> g3 = gen()
>>> g3.__next__()
0
>>> g3.__next__()
1
>>> g3.__next__()
4
>>> g3.__next__()
9
>>> g3.__next__()
16
>>> g3.__next__()
25
>>> g3.__next__()
36
>>> g3.__next__()
49
>>> g3.__next__()
64
>>> g3.__next__()
81
>>> g3.__next__()
Traceback (most recent call last):
File "<pyshell#64>", line 1, in <module>
g3.__next__()
StopIteration
>>>
这种方法太麻烦了,我们一般使用for循环。
补充:
Python的for循环本质上就是不断调用next函数实现的,next函数的参数类型必须是一个Iteraotr生成器(有__next__属性)类型 ps:next函数应该是通过调用生成器对象的__next__ 属性来完成遍历的,因为一个Iterator类型必须实现__next__函数。
>>> g4 = gen()
>>> while True:
try:
x = next(g4)
print(x)
except StopIteration:
break
0
1
4
9
16
25
36
49
64
81
>>>
>>> it = iter('hello')
>>> while True:
try:
x = next(it)
print(x)
except StopIteration:
break
h
e
l
l
o
>>>