迭代器用于从集合中取出元素.而生成器用于”凭空”生成元素
 
在 Python 中,所有集合都可以迭代.在 Python 语言内部,迭代器用于支持:
for 循环 
构建和扩展集合类型 
逐行遍历文本文件 
列表推导,字典推导和集合推导 
元组拆包 
调用函数时,使用 * 拆包实参 
 
迭代协议要求对象的 __iter__ 方法返回一个特殊的迭代器对象,这个迭代器对象实现了 __next__ 方法并通过 StopIteration 异常标识迭代的完成.
 
可迭代对象 Iterable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Iterable (metaclass=ABCMeta) :    __slots__ = ()     @abstractmethod     def  __iter__ (self) :         while  False :             yield  None      @classmethod     def  __subclasshook__ (cls, C) :         if  cls is  Iterable:             return  _check_methods(C, "__iter__" )         return  NotImplemented  
如果对象实现了可以返回迭代器的 __iter__ 方法,那么对象就是可迭代的.
 
对可迭代对象使用 iter 函数,返回的对象就是迭代器.解释器需要迭代对象 x 时,会自动调用 iter(x)
iter 函数做了如下事情:
检查对象是否实现了 __iter__ 方法,如果实现了,则调用.返回并获取一个迭代器 
如果没有实现 __iter__ 方法,但是实现了 __getitem__ 方法,Python 会创建一个迭代器,尝试按循序(从索引 0 开始)获取元素 
如果尝试失败,Python 抛出 TypeError 异常,通常会提示 “C object is not iterable”( C 对象不可迭代),其中 C 是目标对象所属的类 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class  Node :    def  __init__ (self, value) :         self._value = value         self._children = []     def  __repr__ (self) :         return  'Node({!r})' .format(self._value)     def  add_child (self, node) :         self._children.append(node)     def  __iter__ (self) :         return  iter(self._children) 
迭代器 Iterator 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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  
迭代器继承了 Iterable 类,实现了如下方法:
__next__: 返回序列中的下一个元素.如果没有元素了,那么抛出 StopIteration 异常__iter__: 返回 self,以便在应该使用可迭代对象的地方使用迭代器 
示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 s = 'ABC'  for  char in  s:    print(char) it = iter(s)   while  True :    try :         print(next(it))       except  StopIteration:           del  it         break  
StopIteration 异常表明迭代器已经迭代到最后一个元素了.Python 语言内部会处理 for 循环和其他迭代上下文(如列表推导,元组拆包等等)中的 StopIteration 异常
Python 中的迭代器与类型无关,而与协议有关.使用 hasattr 检查是否同时具有 __iter__ 和__next__ 属性
 
如下是一个典型的迭代器示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import  reimport  reprlibRE_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) :         return  SentenceIterator(self.words)   class  SentenceIterator :    def  __init__ (self, words) :         self.words = words         self.index = 0      def  __next__ (self) :         try :             word = self.words[self.index]         except  IndexError:             raise  StopIteration()         self.index += 1          return  word     def  __iter__ (self) :         return  self 
生成器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class  Generator (Iterator) :    __slots__ = ()     def  __next__ (self) :         """Return the next item from the generator.          When exhausted, raise StopIteration.         """         return  self.send(None )     @abstractmethod     def  send (self, value) :         """Send a value into the generator.          Return next yielded value or raise StopIteration.         """         raise  StopIteration     @abstractmethod     def  throw (self, typ, val=None, tb=None) :         """Raise an exception in the generator.          Return next yielded value or raise StopIteration.         """         if  val is  None :             if  tb is  None :                 raise  typ             val = typ()         if  tb is  not  None :             val = val.with_traceback(tb)         raise  val     def  close (self) :         """Raise GeneratorExit inside generator.          """         try :             self.throw(GeneratorExit)         except  (GeneratorExit, StopIteration):             pass          else :             raise  RuntimeError("generator ignored GeneratorExit" )     @classmethod     def  __subclasshook__ (cls, C) :         if  cls is  Generator:             return  _check_methods(C, '__iter__' , '__next__' ,                                   'send' , 'throw' , 'close' )         return  NotImplemented  
生成器可以理解为特殊的迭代器,它继承自 Iterator,实现了如下方法
send: 向生成器发送元素,在调用 next(g) 会生成该元素 
Python 函数的定义体中有 yield 关键字,该函数就是生成器函数.调用生成器函数时,会返回一个生成器对象.也就是说,生成器函数是生成器工厂.
生成器用于 “凭空” 生成元素,见如下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 >>>  def  gen_123 () :....    yield  1  ....    yield  2  ....    yield  3  ... >>>  gen_123<function gen_123 at 0 x...> >>>  gen_123() <generator object gen_123 at 0 x...> >>>  for  i in  gen_123(): ...     print(i)>>>  g = gen_123() >>>  next(g)  >>>  next(g)  >>>  next(g)  >>>  next(g)  Traceback (most recent call last): ... StopIteration 
如下使用生成器代替上述 SentenceIterator 类,Sentence 就是一个生成器,而不用单独创建一个生成器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import  reimport  reprlibRE_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) :         for  word in  self.words:              yield  word            
惰性实现 上述示例在初始化 __init__ 方法一次性构建好了文本中的单词列表,然后将其绑定为 self.words 属性.如下示例是 Sentence 类的惰性实现,在处理数据量较大的情况下,可以节省大量内存.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import  reimport  reprlibRE_WORD = re.compile('\w+' ) class  Sentence :    def  __init__ (self, text) :         self.text = text              def  __repr__ (self) :         return  'Sentence(%s)'  % reprlib.repr(self.text)     def  __iter__ (self) :         for  match in  RE_WORD.finditer(self.text):               yield  match.group()   
生成器表达式 生成器表达式可以理解为列表推导的惰性版本,它并不会迫切的构建列表,而是返回一个生成器,按照需要惰性生成元素.如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 >>>  def  gen_AB () :...  print('start' )...  yield  'A' ...  print('continue' )...  yield  'B' ...  print('end.' )... >>>  res1 = [x*3  for  x in  gen_AB()]  start continue end. >>>  for  i in  res1:  ...  print('-->' , i)... --> AAA --> BBB >>>  res2 = (x*3  for  x in  gen_AB()) >>>  res2 <generator object <genexpr> at 0x10063c240 > >>>  for  i in  res2: ...  print('-->' , i)... start --> AAA continue --> BBB end. 
总结 两者都是可迭代对象,都可以使用 next() 内置函数返回迭代或生成的元素.在元素”耗尽”时,都会抛出 StopIteration 异常
迭代器: 使用 iter() 函数创建.在创建时,所有待迭代的元素已经产生,且全部加载到内存中 
生成器: 使用生成器函数或生成器表达式创建.在创建时所有待生成的元素没有产生,不会有内存的损耗.只有在迭代时,生成器函数的函数体或生成式表达式的逻辑体才会执行,生成元素(懒加载).