迭代器简介:迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
for循环执行步骤:1.判断对象是否是可迭代的(创建对象的类要有__iter__方法)
2.判断对象的__iter__方法的返回值是一个迭代器(返回值有__iter__和__next__ 方法的引用)
3.每次循环调用__next__方法的返回值
初次自定义迭代对象:
1 class Classmate(object): 2 def __init__(self): 3 self.names = list() 4 5 def add(self, name): 6 self.names.append(name) 7 8 9 classmate = Classmate() 10 classmate.add("张三") 11 classmate.add("李四") 12 classmate.add("王五") 13 14 for temp in classmate: 15 print(temp)
运行结果报错:Classmate不是可以迭代的
说明:for循环执行首先会判断对象是否为可迭代的
1 TypeError: 'Classmate' object is not iterable
Classmate类中添加__iter__方法,在循环前加上判断classmate是否是可迭代:
1 def __iter__(self): 2 pass 3 4 ...... 5 6 print('classmate是否是可迭代的:', isinstance(classmate, Iterable))
运行报错:iter()返回类型为非迭代器
说明:for循环判断为可迭代的对象后,会判断对象的iter方法的返回值是否有__iter__和__next__ 方法的引用
1 classmate是否是可迭代的: True 2 TypeError: iter() returned non-iterator of type 'NoneType'
将Classmate类中的__iter__的返回值添加含__iter__ 和__next__ 方法的引用:
1 from collections.abc import Iterable 2 from collections.abc import Iterator 3 4 5 class Classmate(object): 6 def __init__(self): 7 self.names = list() 8 9 def add(self, name): 10 self.names.append(name) 11 12 def __iter__(self): 13 # ClassIterator()相当于创建ClassIterator的对象,return这个对象相当于返回这个对象的引用 14 return ClassIterator() 15 16 17 class ClassIterator(object): 18 def __iter__(self): 19 pass 20 21 def __next__(self): 22 pass 23 24 25 classmate = Classmate() 26 classmate.add("张三") 27 classmate.add("李四") 28 classmate.add("王五") 29 30 31 # print('classmate是否是可迭代的:', isinstance(classmate, Iterable)) 32 classmate_iterator = iter(classmate) # iter(classmate)可以接收_iter__方法的返回值 33 print('classmate_iterator是否是迭代器:', isinstance(classmate_iterator, Iterator)) 34 35 36 for temp in classmate: 37 print(temp)
运行结果:
说明:都判断为True后开始循环取next方法的返回值
1 True 2 None 3 None 4 None 5 None 6 ......
由此,通过设置next方法的返回值可以改变for循环执行的结果。如果要让for循环正确执行,next方法的返回值设置思路为:
1.通过classmate[索引]取得classmate内的元素
2.索引要从0到classmate的元素长度减1,且调用一次next,索引加1
3.通过raise StopIteration 抛出StopIteration异常告诉for循环已经循环结束。此时索引是大于等于classmate元素的长度
for循环要正确执行代码修改如下:
1 class Classmate(object): 2 def __init__(self): 3 self.names = list() 4 5 def add(self, name): 6 self.names.append(name) 7 8 def __iter__(self): 9 # ClassIterator()相当于创建ClassIterator的对象,return这个对象相当于返回这个对象的引用 10 # ClassIterator(self)将自己作为实参传递到ClassIterator这个类 11 # 当ClassIterator类的init方法用 self.名称=形参 时,ClassIterator类的 self.名称 将指向我自己 12 return ClassIterator(self) 13 14 15 class ClassIterator(object): 16 17 def __init__(self, obj): 18 self.obj = obj 19 self.num = 0 20 21 def __iter__(self): 22 pass 23 24 def __next__(self): 25 if self.num < len(self.obj.names): 26 rest = self.obj.names[self.num] 27 self.num += 1 28 return rest 29 else: 30 raise StopIteration 31 32 33 classmate = Classmate() 34 classmate.add("张三") 35 classmate.add("李四") 36 classmate.add("王五") 37 38 39 # print('classmate是否是可迭代的:', isinstance(classmate, Iterable)) 40 # classmate_iterator = iter(classmate) 41 # print('classmate_iterator是否是迭代器:', isinstance(classmate_iterator, Iterator)) 42 43 44 for temp in classmate: 45 print(temp)
运行结果:
1 张三 2 李四 3 王五
可以将Classmate类里面的__iter__方法的返回值设置成自己(self),那么在Classmate类里面添加__next__方法并设置返回值也可以将对象的__iter__方法的返回值设置为一个迭代器,这样精简了代码:
1 class Classmate(object): 2 def __init__(self): 3 self.names = list() 4 5 def add(self, name): 6 self.names.append(name) 7 self.num = 0 8 9 def __iter__(self): 10 return self 11 12 def __next__(self): 13 if self.num < len(self.names): 14 rest = self.names[self.num] 15 self.num += 1 16 return rest 17 else: 18 raise StopIteration 19 20 21 classmate = Classmate() 22 classmate.add("张三") 23 classmate.add("李四") 24 classmate.add("王五") 25 26 for temp in classmate: 27 print(temp)
运行结果:
1 张三 2 李四 3 王五