首页 > 技术文章 > python 可迭代对象和迭代器以及生成器

learningcaiji 2020-10-18 23:25 原文

迭代器、生成器是python学习的重要概念,其在深度学习的数据集加载中应用也非常广泛。本文主要阐述可迭代对象(Iterable),迭代器(Iterator)以及生成器(generator)的主要区别

首先,迭代器均为可迭代对象,生成器是特殊的迭代器,三者关系如下

 

1.可迭代对象(Iterable)

一个对象只要实现了__iter__()方法,那么它就是可迭代对象,可迭代对象可以被for循环使用。

注意,并非所有被for 循环使用的都为可迭代对象,类中定义__getitem__(self, index),也可被for循环使用,但并非是可迭代对象

但自定义的可迭代对象要能在for循环中正确使用,就需要__iter__()实现必须是正确的。定义了__iter__()方法,可以使用iter()函数。

class IterObj:

    def __init__(self):
        self.a = [3, 5, 7, 11, 13, 17, 19]

        self.n = len(self.a)
        self.i = 0


a = IterObj()
iter(a)
>>>TypeError: 'IterObj' object is not iterable

 for i in a:
    print(a)

  >>>

TypeError: 'IterObj' object is not iterable

 

正确的__iter__()方法要返回一个迭代器对象,即可以通过内置iter()函数转成Iterator对象

class IterObj:

    def __init__(self):
        self.a = [3, 5, 7, 11, 13, 17, 19]

    def __iter__(self):
        return iter(self.a)   #返回列表a的迭代器


it = IterObj()
for i in it:
    print(i)


>>>3
   5
   7
   11
   ...

 

2.迭代器(Iterator)

一个对象实现了__iter__()和__next__()方法,那么它就是一个迭代器对象。

class IterObj:

    def __init__(self, flag):
        self.a = [3, 5, 7, 11, 13, 17, 19]
        self.b = [2,3,4,5,6,7,8]

        self.n = len(self.a)
        self.i = 0
        self.flag = flag

    def __iter__(self):
        if self.flag:
            return iter(self.b)   #返回列表b的迭代器
        else:
            return self   #返回自身实例

    def __next__(self):
        while self.i < self.n:
            v = self.a[self.i]
            self.i += 1
            return v
        else:
            self.i = 0
            raise StopIteration()
            

next函数,调用__next__()方法

it = IterObj(1)
next(it)
>>>3

采用for循环遍历it = IterObj(for i in it: #调用__iter__(),flag=1,返回列表b的迭代器

    print(i)
>>> 2 3
4
5   6   7   8 it = IterObj(0) #调用__iter__(),flag=0,返回自身实例迭代器,调用__next__()方法 for i in it: print(i) >>>3
5 7 11   13
17 19

 

3.生成器

定义生成器有两种方式:

  1. 列表生成器
  2. 使用yield定义生成器函数

列表生成式:

g = (x * 2 for x in range(10))
type(g)
>>>generator

next(g)
>>>4

 

yield

def gen():
    for i in range(5):
        yield i 

a = gen()
type(a)
>>>generator

next(a)
>>>0

for i in a:
    print(i)   #从1开始,因为next(a),已经索引了一个元素 
>>>1        
   2
   3
   4

next(a)
>>>StopIteration: #终止迭代,只能迭代一次

yield关键字的函数调用都是生成器,因为yield会自动创建__iter__()和__next__()

 

 

总结

1.__iter__()方法返回迭代器的实例,因为可迭代对象和迭代器都要实现这个方法,所以有两种方法

写法一:用于可迭代对象类的写法,返回该可迭代对象的迭代器类的实例。

写法二:用于迭代器类的写法,直接返回self(即自己本身),表示自身即是自己的迭代器

2.可迭代对象,只用__iter__()方法,返回迭代器实例,用iter函数执行里面内容,生成一个迭代器

 

 迭代器,同时含有__iter__()方法和__next__()方法,__iter__返回迭代器本身实例,for循环执行__next__()内容

生成器,列表生成器(), yield

3.可迭代对象和迭代器最大的区别——能否重复迭代

可迭代对象:能重复迭代,只能用for
迭代器:只能迭代一次,可以通过for或next()迭代

参考博客:

https://juejin.im/post/6844903834381189127

https://xercis.blog.csdn.net/article/details/105242112?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

 

推荐阅读