Python 系列学习之六:迭代类型 Iterator / Iterable

前言

打算写一系列文章来记录自己学习 Python 3 的点滴;

本章节主要介绍的是有关 Python 的 Iterator 和 Iterable 之间的异同;

本文为作者的原创作品,转载需注明出处;

源码分析

Iterable

首先看看 python 源码中有关 Iterable 的源码,

collections.py

1
2
3
4
5
6
7
8
9
10
11
class Iterable(object):
def __init__(self):
"""
:rtype: collections.Iterable[T]
"""
pass

def __iter__(self):
"""
:rtype: collections.Iterator[T]
"""

可见,Iterable 对象中实现了内置方法__iter__用于迭代;

Iterator

看看 python 源码中有关 Iterator 的源码,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Iterator(Iterable):

__slots__ = ()

@abstractmethod
def __next__(self):
'Return the next item from the iterator. When exhausted, raise StopIteration'
raise StopIteration

def __iter__(self):
return self

@classmethod
def __subclasshook__(cls, C):
if cls is Iterator:
return _check_methods(C, '__iter__', '__next__')
return NotImplemented

注意,Iterator 对象继承自 Iterable,并额外实现了内置方法__next__;其实,该方法就是为了支持 Python 的内置函数next(iterator)的调用;还要注意的是,Iterator 继承自 Iterable,所以它可以被 for 语句进行迭代;

next(iterator)

builtins.py

1
2
3
4
5
6
7
8
def next(iterator, default=None): # real signature unknown; restored from __doc__
"""
next(iterator[, default])

Return the next item from the iterator. If default is given and the iterator
is exhausted, it is returned instead of raising StopIteration.
"""
pass

next(iterator)函数是 Python 的一个内置的默认函数,接受一个 Iterator 对象,并返回 next item;next函数中,调用的正是 Iterator.__next__方法获取 next item 的;当取值完毕以后,抛出StopIteration的错误;

特性分析

归纳起来,python 中,listtupledictsetstr以及generator都是 Iterable 类型;

1
2
3
>>> from collections import Iterable
>>> isinstance('fgh', Iterable)
True

可见,字符串是Iterable类型的;

IterableIterator 的源码分析中,我们可以知道,两者的区别是,只有 Iterator 支持使用 next() 内置函数进行迭代的调用;而其他的类型仅仅支持 for 循环的调用方式;

Iterable -> Iterator

python 提供了这样一个内置方法iter(),可以将Iterable对象转换为Iterator对象;

builtins.py

1
2
3
4
5
6
7
8
9
10
def iter(source, sentinel=None): # known special case of iter
"""
iter(iterable) -> iterator
iter(callable, sentinel) -> iterator

Get an iterator from an object. In the first form, the argument must
supply its own iterator, or be a sequence.
In the second form, the callable is called until it returns the sentinel.
"""
pass

从源码的注释中可以看到,可以通过调用iter(iterable)iterable转换为iterator

1
2
3
4
5
>>> r = iter('ABC')
>>> next(r)
'A'
>>> next(r)
'B'

这样,我们将’ABC’转换为了Iterator,于是乎,我们可以通过调用 next 方法来迭代了;

总结

Python 就这两种迭代类型,做到融会贯通以后,以后,见到不同种类的迭代类型就知道该如何直接下手了;