Python中迭代器和生成器的示例详解
迭代器
Iterable
定义
class Iterable(metaclass=ABCMeta): __slots__ = () @abstractmethod def __iter__(self): while False: yield None @classmethod def __subclasshook__(cls, C): if cls is Iterable: if any("__iter__" in B.__dict__ for B in C.__mro__): return True return NotImplemented
由定义可知Iterable必然包含__iter__函数
Iterator
定义
class Iterator(Iterable): __slots__ = () @abstractmethod def __next__(self): 'Return the next item from the iterator. When exhausted, raise StopIteration' raise StopIteration def __iter__(self): return self @classmethod def __subclasshook__(cls, C): if cls is Iterator: if (any("__next__" in B.__dict__ for B in C.__mro__) and any("__iter__" in B.__dict__ for B in C.__mro__)): return True return NotImplemented
从定义可知Iterator包含__next__和__iter__函数,当next超出范围时将抛出StopIteration事件
类型关系
立即学习“Python免费学习笔记(深入)”;
#! /usr/bin/python#-*-coding:utf-8-*-from collections import Iterator,Iterable# 迭代器s = 'abc'l = [1,2,3]d=iter(l)print(isinstance(s,Iterable)) # Trueprint(isinstance(l,Iterable)) # Trueprint(isinstance(s,Iterator)) # Falseprint(isinstance(l,Iterator)) # Falseprint(isinstance(d,Iterable)) # Trueprint(isinstance(d,Iterator)) # True
理论上你可以使用next()来执行__next__(),直到迭代器抛出StopIteration 实际上系统提供了for .. in ..的方式来解析迭代器
l = [1,2,3,4]for i in l: print(i) # 执行结果 # 1# 2# 3# 4
生成器 generator
生成器的本质是一个迭代器
#! /usr/bin/python#-*-coding:utf-8-*-from collections import Iterator,Iterables = (x*2 for x in range(5))print(s)print('Is Iterable:' + str(isinstance(s,Iterable)))print('Is Iterator:' + str(isinstance(s,Iterator)))for x in s: print(x)# 执行结果 # <generator> at 0x000001E61C11F048># Is Iterable:True# Is Iterator:True# 0# 2# 4# 6# 8</generator>
函数中如果存在yield 则该函数是一个生成器对象 在每一次执行next函数时该函数会在上一个yield处开始执行,并在下一个yield处返回(相当于return)
def foo(): print("First") yield 1 print("Second") yield 2f = foo()print(f)a = next(f)print(a)b = next(f)print(b)# <generator># First# 1# Second# 2</generator>
实例
#! /usr/bin/python#-*-coding:utf-8-*-def add(s,x): return s+xdef gen(): for i in range(4): yield ibase = gen()# 由于gen函数中存在yield,所以# for 循环本质是创建了两个generator object,而非执行函数# base = (add(i,10) for i in base)# base = (add(i,10) for i in base)for n in [1,10]: base = (add(i,n) for i in base)# 这里才开始展开生成器# 第一个生成器展开# base = (add(i,10) for i in base)# base = (add(i,10) for i in range(4))# base = (10,11,12,13)## 第二个生成器展开# base = (add(i,10) for i in (10,11,12,13))# base = (20,21,22,23)print(list(base)) # [20,21,22,23]