#  Iterator & IterableIterable: 实现了  __iter__  方法的对象__iter__  和  __next__  方法的对象
Python 中关于迭代有两个概念,第一个是 Iterable,第二个是 Iterator,协议规定 Iterable 的  __iter__ 方法会返回一个 Iterator, Iterator 的  __next__ 方法(Python 2 里是 next)会返回下一个迭代对象,如果迭代结束则抛出 StopIteration 异常。同时,Iterator 自己也是一种 Iterable,所以也需要实现 Iterable 的接口,也就是 __iter__ ,这样在 for 当中两者都可以使用。Iterator 的 __iter__ 只需要返回自己就行了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 a = [1 , 2 , 3 ] print(isinstance (a, Iterable))   print(isinstance (a, Iterator))   iterator_a = iter (a) print(isinstance (iterator_a, Iterator))   for  i in  a:    print(i, end=' ' ) print() for  i in  iterator_a:    print(i, end=' ' ) 
#  for 循环后备机制for 为了兼容性有两种机制,如果对象有 __iter__ 会使用迭代器,但是如果对象没有 __iter__ ,但是实现了 __getitem__ ,会改用下标迭代的方式。
1 2 3 4 5 6 7 8 9 10 11 12 class  Company :    def  __init__ (self, employees ):         self.employees = employees     def  __getitem__ (self, index ):         return  self.employees[index] companies = Company(['A' , 'B' , 'C' ]) for  c in  companies:    print(c) 
#  为什么存在 Iterable 和 IteratorPython 中许多方法直接返回 Iterator,如果 Iterator 自己不是 Iterable 的话,就很不方便,需要先返回一个 Iterable 对象,再让 Iterable 返回 Iterator。
生成器表达式也是一个 Iterator,显然对于生成器表达式直接使用 for 是非常重要的。那么为什么不只保留 Iterator 的接口而还需要设计 Iterable 呢?
许多对象比如 list、dict,是可以重复遍历的,甚至可以同时并发地进行遍历,通过  __iter__  每次返回一个独立的迭代器,就可以保证不同的迭代过程不会互相影响。
而生成器表达式之类的结果往往是一次性的,不可以重复遍历,所以直接返回一个 Iterator 就好。让 Iterator 也实现 Iterable 的兼容就可以很灵活地选择返回哪一种。
总结来说 Iterator 实现的 __iter__  是为了兼容 Iterable 的接口,从而让 Iterator 成为 Iterable 的一种实现。
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 a = [1 , 2 , 3 ] b = [4 , 5 , 6 ] c = zip (a, b)    print(c, type (c))  print(isinstance (c, Iterator))  for  i in  c:    print(i) for  i in  c:    print(i) print('*'  * 10 ) c_list = list (zip (a, b)) for  i in  c_list:    print(i) for  i in  c_list:    print(i)      
#  自定义迭代器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 from  collections.abc import  Iterator, Iterableclass  Company :    def  __init__ (self, employees ):         self.employees = employees     def  __iter__ (self ):         return  MyIterator(self.employees) class  MyIterator (Iterator ):    def  __init__ (self, iter_list ):         self.iter_list = iter_list         self.index = 0                     def  __next__ (self ):         try :             iter_item = self.iter_list[self.index]         except  IndexError:             raise  StopIteration         self.index += 1          return  iter_item company = Company(['A' , 'B' , 'C' ]) for  c in  company:    print(c) company_iter = iter (company) while  True :    try :         print(next (company_iter))     except  StopIteration:         break