1.容器(container)
容器是存储元素的一种数据结构,可进行成员测试,在python中典型的容器有:
- list
- set
- dict
- tuple
- str
- …
容器较容易理解,可参照生活中容器的理解。
2. 可迭代对象(interable)
迭代(interate) 是指按照某种顺序逐个访问序列中的每一项。
大部分容器都是可迭代的,但还有其他对象也可迭代,如文件对象、管道对象,可迭代对象也可用来表示一个包含有限元素的数据结构。
可迭代对象可以是任意对象,只要该对象实现了 __iter__
方法。
可用isinstance()
判断一个对象是否是可迭代对象:
>>>from collections import Interable
>>>isinstance([],Iterable)
True
>>>isinstance('abc',Iterable)
True
__iter__
方法会返回一个迭代器。那么什么是迭代器?
3. 迭代器(interator)
所谓的迭代器就是具有 next
方法的对象( 注:python3中为__next__()
)。在调用 next 方法时,迭代器会返回它的下一个值,如果迭代器中没有值可以返回,会引发一个 StopIteration
异常。所以迭代器本质上是一个产生值的工厂,每次向迭代器请求下一个值,迭代器都会进行计算出相应的值并返回。
可用 isinstance()
判断一个对象是否是迭代器:
>>>from collections import Iterator
>>>isinstance ((x for x in range(2)), Iterator)
True
>>>isinstance([],Iterator)
False
一般来说,迭代器本身也是可迭代的,即迭代器有返回自己的 next 方法。
>>>from collections import Iterator
>>>isinstance ((x for x in range(2)), Iterator)
True
但list
、dict
、str
等虽然都是可迭代对象,却不是迭代器。但可以使用 iter()
来使可迭代对象变成迭代器。
>>> x=[1,2,3]
>>> y=iter(x)
>>> type(x)
<type 'list'>
>>> type(y)
<type 'listiterator'>
>>> next(x)
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
next(x)
TypeError: list object is not an iterator
>>> next(y)
1
>>> dir(y)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__length_hint__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'next']
可以看出,x 是可迭代对象,y 是迭代器,在迭代器中,有
__iter__()
以及next()
方法。
所有itertools
模块中的函数都会返回一个迭代器。
综上: 可得出 生成迭代器的两种方法 :
- 为容器对象添加
__iter__()
和next()
方法(Python 3 中是next()
);iter() 返回迭代器对象本身 self, next() 则返回每次调用 next()时或迭代时的元素; - 内置函数
iter()
将可迭代对象转化为迭代器
可自定义实现一个迭代器对象:
class MyRange(object):
def __init__(self, n):
print " I made this iterator!"
self.i = 1
self.n = n
def __iter__(self):
return self
def next(self):
print " Calling __next__ method!"
if self.i <= self.n:
i = self.i
self.i += 1
return i
else:
raise StopIteration()
if __name__ == "__main__":
x = MyRange(6)
for i in x:
print i
`
运行结果是
I made this iterator!
Calling __next__ method!
1
Calling __next__ method!
2
Calling __next__ method!
3
Calling __next__ method!
4
Calling __next__ method!
5
Calling __next__ method!
6
Calling __next__ method!
>>>
看出来了吗?上面的代码其实就是自己实现的
range()
函数呢,而 for 语句其实时调用了迭代器的 next 函数。
4. 小结
- 在 Python 中,迭代器是遵循迭代协议的对象。
- 可以使用iter() 以从任何序列得到迭代器(如 list, tuple, dictionary, set 等)。
- 编写类,实现
__iter__()
方法,以及next()
(Python 2)或__next__()
(Python 3) 。当没有元素时,则引发 StopIteration异常。 - 如果有很多值,列表就会占用太多的内存,而迭代器则占用更少内存,每次只记录一个值。
- 迭代器从第一个元素开始访问,直到所有的元素被访问完结束,只能往前不会后退。
请多多指教!