PHP前端开发

Python中迭代器和生成器的示例详解

百变鹏仔 2小时前 #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&gt;# 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]