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 循环.

 

posted @ 2021-01-27 14:55  云long  阅读(158)  评论(0编辑  收藏  举报