该理解是从《流畅的python》一书中进行学习和总结
序列可以迭代的原因:iter函数
解释器需要迭代对象 x 时,会自动调用 iter(x)。
内置的 iter 函数有以下作用。
(1) 检查对象是否实现了 iter 方法,如果实现了就调用它,获取一个迭代器。
(2) 如果没有实现 iter 方法,但是实现了 getitem 方法,Python 会创建一个迭 代器,尝试按顺序(从索引 0 开始)获取元素。
(3) 如果尝试失败,Python 抛出 TypeError 异常,
其中迭代器分为可迭代的对象和迭代器
可迭代的对象与迭代器的对比
可迭代的对象
使用 iter 内置函数可以获取迭代器的对象。如果对象实现了能返回迭代器的 iter 方法,那么对象就是可迭代的。序列都可以迭代;实现了 getitem 方 法,而且其参数是从零开始的索引,这种对象也可以迭代。
我们要明确可迭代的对象和迭代器之间的关系:Python 从可迭代的对象中获取迭代器。
迭代器
迭代器是这样的对象:实现了无参数的 next 方法,返回序列中的下一个元素; 如果没有元素了,那么抛出 StopIteration 异常。Python 中的迭代器还实现了 iter 方法,因此迭代器也可以迭代。
生成器函数的工作原理
只要 Python 函数的定义体中有 yield 关键字,该函数就是生成器函数。调用生成器函数 时,会返回一个生成器对象。也就是说,生成器函数是生成器工厂。
惰性实现
生成器表达式
生成器表达式可以理解为列表推导的惰性版本:不会迫切地构建列表,而是返回一个生成 器,按需惰性生成元素。也就是说,如果列表推导是制造列表的工厂,那么生成器表达式 就是制造生成器的工厂。
生成器和迭代器的区别
迭代器的实现细节
import re
import reprlib
RE_WORD = re.compile('\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): # <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
f = Sentence('wo xiangyao diannao')
这句话生成了一个Sentence对象,因为该类中实现了__iter__ 所以该对象是可迭代的,但是
isinstance(f, abc.Iterable)
True
f = iter(f)
next(f)
'wo'
这就是迭代器模式的实现
但是其代码不够精简
import re
import reprlib
RE_WORD = re.compile('\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): # <1>
return (match.group() for match in RE_WORD.finditer(self.text))
#在这里使用了生成器表达式,调用__iter__ 会得到一个生成器对象
迭代器实现依赖于可迭代对象,并不一定使用到了生成器函数
但是使用了生成器函数的对象,其对象是可迭代的