PDF版 ePub版

# 迭代和可迭代

• 迭代（Iteration）
• 可迭代对象（Iterable）

numbers = [1, 2, 3, 4]
for num in numbers:
print num

>>> hasattr((), '__iter__')
True
>>> hasattr([], '__iter__')
True
>>> hasattr({}, '__iter__')
True
>>> hasattr(123, '__iter__')
False
>>> hasattr('abc', '__iter__')
False
>>> hasattr('abc', '__getitem__')
True

>>> from collections import Iterable

>>> isinstance((), Iterable)        # 元组
True
>>> isinstance([], Iterable)        # 列表
True
>>> isinstance({}, Iterable)        # 字典
True
>>> isinstance('abc', Iterable)     # 字符串
True
>>> isinstance(100, Iterable)       # 数字
False

# 迭代器

>>> hasattr((1, 2, 3), '__iter__')
True
>>> hasattr((1, 2, 3), 'next')  # 有 __iter__ 方法但是没有 next 方法，不是迭代器
False
>>>
>>> hasattr([1, 2, 3], '__iter__')
True
>>> hasattr([1, 2, 3], 'next')
False
>>>
>>> hasattr({'a': 1, 'b': 2}, '__iter__')
True
>>> hasattr({'a': 1, 'b': 2}, 'next')
False

>>> from collections import Iterator
>>>
>>> isinstance((), Iterator)
False
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('', Iterator)
False
>>> isinstance(123, Iterator)
False

>>> from collections import Iterator
>>> isinstance(iter([1, 2, 3]), Iterator)  # 使用 iter() 函数，获得迭代器对象
True
>>> isinstance(iter('abc'), Iterator)
True
>>>
>>> my_str = 'abc'
>>> next(my_str)      # my_str 不是迭代器，不能使用 next()，因此出错
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-5f369cd8082f> in <module>()
----> 1 next(my_str)

TypeError: str object is not an iterator
>>>
>>> my_iter = iter(my_str)   # 获得迭代器对象
>>> isinstance(my_iter, Iterator)
True
>>> next(my_iter)   # 可使用内置的 next() 函数获得下一个元素
'a'

for x in [1, 2, 3]:
print i

# 获得 Iterator 对象
it = iter([1, 2, 3])

# 循环
while True:
try:
# 获得下一个值
x = next(it)
print x
except StopIteration:
# 没有后续元素，退出循环
break

# 斐波那契数列迭代器

# -*- coding: utf-8 -*-

from collections import Iterator

class Fib(object):
def __init__(self):
self.a, self.b = 0, 1

# 返回迭代器对象本身
def __iter__(self):
return self

# 返回容器下一个元素
def next(self):
self.a, self.b = self.b, self.a + self.b
return self.a

def main():
fib = Fib()    # fib 是一个迭代器
print 'isinstance(fib, Iterator): ', isinstance(fib, Iterator)

for i in fib:
if i > 10:
break
print i

if __name__ == '__main__':
main()

isinstance(fib, Iterator):  True
1
1
2
3
5
8

# 小结

• 元组、列表、字典和字符串对象是可迭代的，但不是迭代器，不过我们可以通过 iter() 函数获得一个迭代器对象；
• Python 的 for 循环实质上是先通过内置函数 iter() 获得一个迭代器，然后再不断调用 next() 函数实现的；
• 自定义迭代器需要实现对象的 __iter()__next() 方法（注意：Python3 要实现 __next__() 方法），其中，__iter()__ 方法返回迭代器对象本身，next() 方法返回容器的下一个元素，在没有后续元素时抛出 StopIteration 异常。