Python3 迭代器迭代对象疑问的总结
1.可迭代对象Iterable和迭代器Iterator的区别
Iterable中实现__iter__方法,__iter__方法会返回一个Iterator。注意,这里返回的是一个迭代器。自定义可迭代类的时候,要返回一个迭代器,不能return self,自己不是一个迭代器。
迭代器继承自Iterable,实现__next__,可以重写__iter__。自定义一个迭代器,__iter__中可以return self,自己实现了__next__,就是个迭代器。
2.iter()方法做了什么?
l = [1,2,3,4] a = iter(l) #iter()调用了列表的__iter__,返回l迭代器对象,使a能使用__next__
3.for循环原理
for 循环在工作时,首先会调用可迭代对象内置的iter方法拿到一个迭代器对象,然后再调用该迭代器对象的next方法将取到的值赋给item,执行循环体完成一次循环,周而复始,直到捕捉StopIteration异常,结束迭代
4.getitem 也是模拟的返回一个迭代器
for循环中,如果对象没有__iter__,但是实现了__getitem__,会改用下标迭代的方式
class Person: def __init__(self,persion_list): self.persion_list=persion_list def __getitem__(self, item): return self.persion_list[item] body=Person(["Xiuwu","Adny","Maggie"]) for i in body: print (i)
当for发现没有__iter__但是有__getitem__的时候,会从0开始依次读取相应的下标,直到发生IndexError为止,这是一种旧的迭代协议。
5.有些可迭代对象中__iter__,返回的是return iter(some_cls),这里 __iter_ 方法 是需要通过 iter() 显示的转成 iterator.
class test: # test 类支持迭代协议,因为它定义有__iter__()函数 def __iter__(self): self.result=[1,2,3] return iter(self.result) #返回的是可迭代对象 a = test() print(type(a)) b = iter(a) #b 拥有了__next__方法(next(b)),调用a的__iter__方法 print(next(b))
6.自定义迭代器
class Person: def __init__(self): self.n = 0 def __iter__(self): return self def __next__(self): while True: if self.n > 6: raise StopIteration self.n += 1 return self.n a = Person() b = iter(a) # print(next(b)) # print(next(b)) # print(next(b)) # print(next(b)) # print(next(b)) # print(next(b)) # print(next(b)) # print(next(b)) for i in iter(a): print("sd") print(i)
from collections import Iterable, Iterator class Person: def __init__(self, persion_list): self.persion_list = persion_list def __iter__(self): return Myiterator(self.persion_list) #调用我们重写的迭代器方法 #def __iter__(self): # return 1 #def __getitem__(self, item): #把这个方法用我们自己写的迭代器方法替代. # return self.persion_list[item] class Myiterator(Iterator): #继承Iterator 就不需要写__iter__,直接调用父类的. def __init__(self,persion_list): self.persion_list=persion_list self.index=0 #由于iterator 是没有index 的,这个要我们手动添加 def __next__(self): #这个就是迭代器的取值逻辑 while True: #当为false 的时候结束循环 try: word = self.persion_list[self.index] #取值动作 except IndexError: #index 当变得超出persion_list 会报错的 ,先抓住这个异常 raise StopIteration #迭代到没有值要用这异常,咱们把异常做个转化 self.index = self.index + 1 #递增我们的index return word #返回取到的值 body = Person(["Xiuwu", "Adny", "Maggie"]) a=iter(body) #调用我们自定义的迭代器方法 print(a) # <__main__.Myiterator object at 0x00000000022399B0> #从打印结果看说明我们自定义的迭代器方法生效了,已经返回一个迭代器 print(next(a)) #Xiuwu #从打印结果我们判断出 __next__生效,如果想循环输出,自己试试for 循环.