python进阶——生成器系列之迭代器与反向迭代

花间影清欢课程 2024-03-30 23:12:22
引子在python中,生成器无疑是最有用的特性之一,但也是使用最不广泛的特性之一,究其原因,主要是因为在其他主流语言中没有生成器概念,正是由于生成器是一个“新”的概念,所以它一方面没有引有重视,另一方面也增加了学习成本,最终导致大家错过了python中如此有用的一个特性。要理解生成器需要先理解迭代器与迭代器协议,下面我将通过整篇文章分享迭代器与迭代器协议相关内容。 一、什么是迭代器迭代器:一个可以记住遍历位置的对象;可迭代对象:实现了迭代器协议的对象;迭代器协议:python迭代器协议要求一个__iter__()方法返回一个特殊的迭代器对象,这个迭代器对象实现了__next__()方法并可通过StopIteration异常标识迭代的完成。二、举例说明在所有语言中,我们都可以使用for循环来遍历数组,python的list底层实现是一个数组,所以我们可以使用for循环来遍历list。如下所示: for n in [1, 2, 3, 4]: print(n)我们不只可以使用for循环来遍历list,也可以用来遍历文件对象,如下所示: with open(‘/etc/passwd’) as f: # 文件对象提供迭代器协议 for line in f: # for循环使用迭代器协议访问文件 print(line)这是因为在python中,文件对象实现了迭代器协议,for循环并不知道它遍历的是一个文件对象,它只管使用迭代器协议访问对象即可。正是由于python的文件对象实现了迭代器协议,我们才可以如此方便循环处理文件对象: >>> f_obj = open('/etc/profile')>>> dir(f_obj)['__class__', '__enter__', '__exit__', '__iter__', '__new__', 'writerlines', ...]三、自定义迭代器3.1 问题如何构建一个能支持迭代操作的自定义对象? 3.2 解决方案要实现一个支持迭代操作的自定义对象,那么这个对象需要实现迭代器协议,而python的迭代器协议要求自定义类中需要实现__iter__()和__next__()方法。并且可以通过StopIteration异常来标识迭代已完成。 class UserDefineIterator(): def __init__(self, max): self.max = max self.num= 1 def __iter__(self): return self def __next__(self): if self.num <= self.max: num="self.num" self.num +="2" return else: raise stopiteration3.3 测试>>> i = UserDefineIterator(5)>>> next(i)1>>> next(i)3>>> next(i)5四、反向迭代反向迭代仅仅当对象的大小可预先确定或者对象实现了__reversed__()方法时才可以使用,如果两者都不符合,就需要先将对象转为一个列表才可以,如下所示: # Print a file backwardsf = open('somefile')for line in reversed(list(f)): print(line, end='')4.1 实现一个自定义的可反向迭代对象,如下所示:class Countdown: def __init__(self, start): self.start = start # Forward iterator def __iter__(self): n = self.start while n > 0: yield n n -= 1 # Reverse iterator def __reversed__(self): n = 1 while n
0 阅读:0