python 迭代器

来源:互联网 发布:环信java需要哪些jar包 编辑:程序博客网 时间:2024/05/22 08:06

1.容器(container)

容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个迭代获取,可以用in,not in关键字判断元素是否包含在容器中。通常这类数据结构把所有的元素存储在内存中(也有一些特殊的存在)。再Python中常见的容器对象:

1. list ,deque, ...2. set, frozensets, ...3. dict, defaultdict, OrderedDict, Counter, ...4. tuple, nametuple, ...5. str
1.可迭代对象赋予容器一种可以供提取元素的能力2.不是所有的容器都是可迭代的

2.可迭代对象(iterable)

如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)

可迭代对向 并不局限于容器,如:files,sockets等(处于打开状态)。只要是可用i返回有一个可迭代的对象都可以称之为可迭代对象,懵逼。。。
先看实例吧:

x = [1, 2, 3]y = iter(x)print(next(y))print(next(y))print(type(x), type(y))>>>12<class 'list'> <class 'list_iterator'>

分析:

这里x是一个可迭代对象,可迭代对象和容器一样是一种通俗的称呼,并不是指某种具体的数据类型。list,set,dict都是可迭代对象而y则是一个独立的迭代器,迭代器内部有一个状态,该状态用于记录当前迭代坐在的位置,以方便下次迭代的时获取正确的元素。迭代器有一种具体的迭代器类型:list_iterator,set_iterator, …。可迭代对象实现了iter()和next()方法(python2中是next()方法,python3.x是next()方法),这两个方法对应内置函数iter()和next()。iter方法返回可迭代对象本身,这使得它既有可迭代对象同时也是一个迭代器。

3.迭代器

迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来。
  
迭代器具备以下两种方法:

iter()
next()
而可迭代对象必须具备:

iter()
1.对于迭代器来讲,有一个next()就够了。在使用for循环时,程序会自动调用即将被处理的迭代器对象,然后使用next()函数,直到检测到一个StopIteration异常。
2.next()内置函数就是调用对象的方法next(),iter()内置函数是调用对象的iter()方法

代码验证:

直接调用next()方法

>>> L = [1, 2, 3]>>> next(L) Traceback (most recent call last):  File "<input>", line 2, in <module>TypeError: 'list' object is not an iterator>>> L = [1, 2, 3]>>> print(type(L))<class 'list'>

先使用iter(),再调用next()

>>> L = [1, 2, 3]>>> I = iter(L) >>> next(I)1>>> next(I)2>>> next(I)3>>> next(I)Traceback (most recent call last):  File "<input>", line 1, in <module>StopIteration   #异常>>> print(type(I))<class 'list_iterator'>

由此可见,L可以用for循环取值,不能用next(),因此判断L是iterable;当L通过iter()进行包装后,就可以调用next()取值了,此时L是iterator了.

除了上述方式可以判断,还有相应的判断函数:

可迭代对象判断

>>> from collections import Iterable>>> isinstance([], Iterable)True>>> isinstance({}, Iterable)True>>> isinstance((), Iterable)True>>> isinstance('abc', Iterable)True>>> isinstance(1000, Iterable)False

迭代器判断

>>> from collections import Iterator>>> isinstance([x for x in range(9)], Iterator)False>>> isinstance((x for x in range(9)), Iterator)True>>> isinstance(1000, Iterator)False>>> isinstance({}, Iterator)False>>> isinstance([], Iterator)False>>> isinstance((), Iterator)False>>> isinstance('abc', Iterator)False

当使用iter()将可迭代对象进行转化后,就能够满足判断条件:

>>> isinstance(iter('abc'), Iterator)True>>> isinstance(iter([]), Iterator)True

===>至此,我们可以推断: for循环内部就是先调用iter()把iterable变成iterator再进行循环迭代。

这里写图片描述

实际上,完全等价于:

L = [1, 2, 3]for i in L:    passI = iter(L) #获取迭代器对象while True: #循环    try:        x = next(I)  #获取下一值    except StopIteration:        break   #捕捉到该异常退出循环

此时,还有懵逼这里写图片描述的地方:为什么list, dict, set, str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()内置函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration异常。可以把这个数据流看做是一个有序序列,但是不能提前知道这个序列的长度,只能不断通过next()内置函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时才会计算。Iterator可以看做是无限大的数据流,eg:全体自然数,而list,set, str等是不可能存储全部的自然数的。

扩展 Iterator继承自Iterable,从下面的测试中可以很方便的看到Iterator包含iter()和next()方法,而Iteratble仅仅包含iter()。

>>> from collections  import  Iterator, Iterable>>> help(Iterator)Help on class Iterator in module collections.abc:class Iterator(Iterable) |  Method resolution order: |      Iterator |      Iterable |      builtins.object |   |  Methods defined here: |   |  __iter__(self) |   |  __next__(self) |      Return the next item from the iterator. When exhausted, raise StopIteration>>> help(Iterable)Help on class Iterable in module collections.abc:class Iterable(builtins.object) |  Methods defined here: |   |  __iter__(self)

4.小结

用for循环迭代的对象都是Iterable类型
用next()内置函数取值的对象都是Iterator类型,表示一个惰性计算的序列
Iterable均可通过内置函数iter(),获得一个Iterator对象
for循环内部实现机制

0 0