可迭代对象(iterable)和迭代器对象(iterator)的概念是如此相似,常常容易混淆,今天就来梳理区分一下。
可迭代对象
可迭代对象简单来说这个对象是可以迭代的,例如 list,tuple,set,dict,str 等。可以利用 for 来循环的对象都是可迭代对象。
可以利用 isinstance() 函数来判断对象的类型 :
>>> from collections import Iterable
>>> isinstance([],Iterable)
True
>>> isinstance({},Iterable)
True
>>> isinstance(1,Iterable)
False
迭代器对象
迭代器对象是可以被 next() 函数不断调用并返回下一个值的对象 。
在说迭代器之前,首先看一下什么是生成器,生成器可以说是一种可以根据推导算法来推出当前值,它存储的是推导算法推出来的当前值,因此,与列表生成式不同:
1.生成器存储的是当前值,因此占用内存空间比较小。
2.不用事先计算要存多少数据,而列表生成式和数组类似,事先要考虑存多少数据进去,存入数据以后,空间大小就固定了。
3.列表生成式存储的数据有限,而生成器由于存储的是算法,因此可以不断通过算法推导下一个值,也就是说,生成器可以存储的数据是无限的。
生成器(generator)有两种构建方法:
1.通过小括号()构建,也就是将生成器的 [] 直接改成 ()就得到一个迭代器。
# 使用小括号()创建生成器
>>> a = [x for x in range(3)]
>>> a
[0, 1, 2]
>>> b = (x for x in range(3))
>>> b
<generator object <genexpr> at 0x10c8ee0c0>
2.在函数中使用 yield 构建。
# 在函数中添加 yield 构建生成器
>>> def odd():
... yield 1
... yield 3
... yield 5
...
>>> c = odd
>>> c
<function odd at 0x10c7e6620>
>>> d = odd()
>>> d
<generator object odd at 0x10c8ee1b0>
生成器可以通过 next() 来不断获取下一个值,直到没有值,抛出 StopIteration 异常。
>>> next(a)
0
>>> next(a)
1
>>> next(a)
2
>>> next(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> next(d)
1
>>> next(d)
3
>>> next(d)
5
>>> next(d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
因此,生成器都是迭代器对象(iterator),而迭代器对象无疑又是可迭代的,使用 for 循环对迭代器对象进行迭代,不会抛出异常,也不会抛出一个值就中断,而是一次输出迭代器中的所有值。
for i in a:
print(i)
总之,迭代器对象是一个有序数据流,提前不知道他的长度,他是惰性计算的,只有需要返回下一个数据的时候,才会计算并返回数据。 |