迭代器和可迭代对象

from collections import Iterable, Iterator


class ClassIterator:
    """迭代器必须实现__iter__和__next__方法,故迭代器一定是可迭代对象"""
    def __init__(self, obj):
        self.obj = obj
        self.position = 0

    def __iter__(self):
        pass

    def __next__(self):
        if self.position < len(self.obj.names):
            next_value = self.obj.names[self.position]
            self.position += 1
            return next_value
        else:
            raise StopIteration


class ClassMate:
    """只要实现了__iter__方法就是可迭代对象,可迭代对象返回一个迭代器"""
    def __init__(self):
        self.names = ["zhang san", "li si", "wang wu"]

    def __iter__(self):
        return ClassIterator(self)


classmate = ClassMate()
class_iterator = ClassIterator(classmate)

print(isinstance(classmate, Iterable))  # 返回True,因为实现了__iter__方法,所以是可迭代对象
print(isinstance(classmate, Iterator))  # 返回false,因为没有实现__next__方法,所以不是迭代器
print(isinstance(class_iterator, Iterable))  # 返回True,实现了__iter__
print(isinstance(class_iterator, Iterator))  # 返回True,实现了__iter__和__next__

"""for语句首先用iter(classmate)获取一个迭代器,然后用next(迭代器)逐个获取元素,直到捕捉到StopIteration"""
for i in classmate:
    print(i)

总结:

1、对象A重载了__iter__方法(甚至方法体是pass),那么A就是可迭代对象,即isinstance(A,Iterable)返回True

2、对象A重载了__iter__方法和__next__方法,那么A就是一个迭代器,即isinstance(A,Iterator)返回True

3、iter(A)触发A的__iter__方法,__iter__返回一个迭代器

4、next(迭代器)触发迭代器的__next__方法

5、for i in A的执行流程为:先调用iter(A)获取一个迭代器B,然后执行next(B),直到B抛出StopIteration异常

 

事实上,迭代器和可迭代对象可以合二为一,当一个对象实现了__iter__和__next__,那么它既是可迭代对象,又是迭代器,__iter__可以返回它自己,而不需要额外去写一个迭代器,比如上面的示例可以简化为:

class ClassMate:
    def __init__(self):
        self.names = ["zhang san", "li si", "wang wu"]
        self.position = 0

    def __iter__(self): # 本身是一个迭代器
        return self

    def __next__(self):
        if self.position < len(self.names):
            next_value = self.names[self.position]
            self.position += 1
            return next_value
        else:
            raise StopIteration


classmate = ClassMate()

for i in classmate:
    print(i)

 

posted @ 2020-03-31 00:04  olivertian  阅读(249)  评论(0编辑  收藏  举报