python模块学习:Iterators和Generators
2017-07-04 14:29 很大很老实 阅读(651) 评论(0) 编辑 收藏 举报转自:http://www.cnblogs.com/zhbzz2007/p/6102695.html
1 迭代器:
迭代器,允许你在一个容器上进行迭代的对象。
python的迭代器主要是通过__iter__和__next__两个方法来实现。
__iter__,要求你的容器支持迭代,返回对象本身。如果想创建一个迭代器对象,还需要实现__next__方法,这个返回下一个对象。
为了对这些概念更加清晰,让我们回顾下面的两个定义:
- 可迭代对象(iterable),只定义了__iter__方法;
- 迭代器(iterator),定义了__iter__和__next__两个方法,__iter__返回迭代器本身,__next__方法返回下一个元素
所有函数名中有双下划线的方法,都很神奇,你不需要直接调用__iter__或者__next__。你可以使用for循环或者转换为列表,Python就会自动替你调用这些方法。当然你或许还是想调用它们,那么你可以使用Python内置的函数iter和next方法。
python3中,list是支持迭代的,但不是迭代器对象。因为,它不支持__next__
看代码:
a=[1,2,3,4,5]
next(a)
错误信息是:
C:\Python35\python.exe C:/Users/wcf/PycharmProjects/Algorithms/wcf.py Traceback (most recent call last): File "C:/Users/wcf/PycharmProjects/Algorithms/wcf.py", line 3, in <module> next(a) TypeError: 'list' object is not an iterator Process finished with exit code 1
通过iter内建函数,可以把他转变成迭代器:
a=[1,2,3,4,5] for item in iter(a): print(item)
当你使用循环来遍历一个迭代器,你就不需要调用next方法,你也无需担心会收到StopIteration异常信息。
比如:
a=[1,2,3,4,5] a_iter=iter(a) next(a_iter) next(a_iter) next(a_iter) next(a_iter) next(a_iter) next(a_iter) next(a_iter)
会出错的:
C:\Python35\python.exe C:/Users/wcf/PycharmProjects/Algorithms/wcf.py Traceback (most recent call last): File "C:/Users/wcf/PycharmProjects/Algorithms/wcf.py", line 10, in <module> next(a_iter) StopIteration Process finished with exit code 1
2.创建属于自己的迭代器,很简单,实现几个方法就可以:
class my_iterator(): def __init__(self,letters): self.letters=letters self.position=0 def __iter__(self): return self def __next__(self): if self.position>=len(self.letters): raise StopIteration letter=self.letters[self.position] self.position+=1 return letter if __name__=="__main__": i=my_iterator('abcd') for item in i: print(item)
3.生成器
一个普通的Python函数经常返回一个值,无论它是列表、整数还是其他对象。但是如果你想调用一个函数,这个函数能否产生一系列值呢?这个就是生成器诞生的原因。生成器的工作机制是保存它所停止(或者说它已经产生)的位置,然后给主调函数返回一个值。不是返回一个调用函数的执行,生成器仅仅返回一个临时的控制返回。为了完成这个功能,生成器函数需要使用Python的 yield 语句。
def double_generator(): number=2 while True: yield number number+=2 doubler =double_generator() print(next(doubler)) print(next(doubler)) print(next(doubler)) print(next(doubler))
输出是:
C:\Python35\python.exe C:/Users/wcf/PycharmProjects/Algorithms/wcf.py 2 4 6 8 Process finished with exit code 0
实际上,上文,也有一个next方法。
而下面的例子,就是没有:
def double_generator(): yield 'wcf1' yield 'wcf2' yield 'wcf3' doubler =double_generator() print(next(doubler)) print(next(doubler)) print(next(doubler))
输出是:
C:\Python35\python.exe C:/Users/wcf/PycharmProjects/Algorithms/wcf.py
wcf1
wcf2
wcf3
Process finished with exit code 0
同样的,如果是:
def double_generator(): yield 'wcf1' yield 'wcf2' yield 'wcf3' doubler =double_generator() print(next(doubler)) print(next(doubler)) print(next(doubler)) print(next(doubler))
一样会触发一场:
C:\Python35\python.exe C:/Users/wcf/PycharmProjects/Algorithms/wcf.py wcf1 Traceback (most recent call last): wcf2 wcf3 File "C:/Users/wcf/PycharmProjects/Algorithms/wcf.py", line 12, in <module> print(next(doubler)) StopIteration Process finished with exit code 1
而这样写,就ok:
def double_generator(): yield 'wcf1' yield 'wcf2' yield 'wcf3' doubler =double_generator() for item in doubler: print(item)