python 可迭代对象和迭代器以及生成器
迭代器、生成器是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.生成器
定义生成器有两种方式:
- 列表生成器
- 使用
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