1 为什么需要迭代器
迭代器模式是一种行为设计模式, 能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。
使用多种集合的客户端代码可能并不关心存储数据的方式。 不过由于集合提供不同的元素访问方式, 代码将不得不与特定集合类进行耦合。迭代器模式的主要思想是将集合的遍历行为抽取为单独的迭代器对象。
迭代器在处理数据流、文件内容、或其他形式的序列数据时特别有用。使用相同的迭代方式处理任何可迭代的数据类型。
2 python迭代器原理
-
可迭代对象
在Python中,任何实现了__iter__()方法的对象都是可迭代的。iter()方法需要返回一个迭代器。这意味着,当你在一个对象上调用iter()函数时,实际上是在调用它的__iter__()方法。例如,列表、元组、字典、文件等都是可迭代对象。 -
迭代器对象
迭代器是一个具体的对象,它管理迭代过程。为了成为一个迭代器,对象必须实现两个方法:iter():它返回迭代器对象本身。这样做是为了兼容那些不区分迭代器和可迭代对象的使用场景。
next():它返回容器的下一个元素。当没有更多元素时,next()应该抛出一个StopIteration异常。
可迭代对象与迭代器之间的关系:Python从可迭代对象中获取迭代器。
检查对象是否实现了__iter__方法,如果实现了就调用它,获取一个迭代器。
如果没有实现,但是实现了__getitem__方法,那么iter()创建一个迭代器,尝试按索引(从0开始)获取项。
如果尝试失败,则Python抛出TypeError异常,通常会提示'C' object is not iterable(C对象不可迭代),其中C是目标对象所属的类。
3 python迭代器示例
3.1 Sentence类第1版:单词序列
class Sentence:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text)
def __getitem__(self, index):
return self.words[index]
def __len__(self):
return len(self.words)
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
>>> s = Sentence('The time has come')
>>> s
Sentence('The time has come')
>>> list(s)
['The', 'time', 'has', 'come']
>>> it = iter(s)
>>> next(it)
'The'
>>> next(it)
'time'
>>> next(it)
'has'
>>> next(it)
'come'
>>> next(it)
Traceback (most recent call last):
...
StopIteration
3.2 Sentence类第2版:经典迭代器
删除__getitem__方法。
添加__iter__方法,初始化SentenceIterator类,返回一个迭代器。
添加SentenceIterator类,实现__next__和__iter__方法。
class Sentence:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text)
def __repr__(self):
return f'Sentence({reprlib.repr(self.text)})'
def __iter__(self): # <1>
return SentenceIterator(self.words) # <2>
class SentenceIterator:
def __init__(self, words):
self.words = words # <3>
self.index = 0 # <4>
def __next__(self):
try:
word = self.words[self.index] # <5>
except IndexError:
raise StopIteration() # <6>
self.index += 1 # <7>
return word # <8>
def __iter__(self): # <9>
return self
3.3 Sentence类第3版:生成器函数
添加__iter__方法:遍历单词数组,使用yield创建生成器。
只要Python函数的主体中有yield关键字,该函数就是生成器函数。调用生成器函数,返回一个生成器对象。
生成器工作原理:
生成器函数创建一个生成器对象,包装生成器函数的主体。
把生成器对象传给next()函数时,生成器函数提前执行函数主体中的下一个yield语句,返回产出的值,并在函数主体的当前位置暂停。
函数的主体返回时,Python创建的外层生成器对象抛出StopIteration异常。
RE_WORD = re.compile(r'\w+')
class Sentence:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text)
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self):
for word in self.words:
yield word
3.4 Sentence类第4版:惰性生成器
修改__iter__方法,用正则表达式分割句子,并用yield返回迭代对象。
迭代器:泛指实现了__next__方法的对象。迭代器用于生成供客户代码使用的数据,即客户代码通过for循环或其他迭代方式,或者直接在迭代器上调用``next(it)`驱动迭代器。
生成器:由Python编译器构建的迭代器。为了创建生成器,使用yield关键字得到生成器函数。生成器表达式是构建生成器对象的另一种方式。
RE_WORD = re.compile(r'\w+')
class Sentence:
def __init__(self, text):
self.text = text # <1>
def __repr__(self):
return f'Sentence({reprlib.repr(self.text)})'
def __iter__(self):
for match in RE_WORD.finditer(self.text):
yield match.group()
3.5 Sentence类第5版:惰性生成器表达式
修改__iter__方法:使用生成器表达式构建生成器对象。
import re
import reprlib
RE_WORD = re.compile(r'\w+')
class SentenceV5:
def __init__(self, text):
self.text = text
def __repr__(self):
return f'Sentence({reprlib.repr(self.text)})'
def __iter__(self):
return (match.group() for match in RE_WORD.finditer(self.text))