猴子都能看懂的迭代器、生成器、可迭代对象解析(python)

迭代器、生成器、可迭代对象、迭代器协议

先说好这篇文章是根据python3.6 写出来的,其他语言博主不清楚是否和Python一样

  1. 迭代器协议在Python3.6的文档(4.5. Iterator Types)中定义如下:实现 _iter_(),_next_()两中方法的容器(可以理解为类)称之为迭代器,其中_iter_() 方法返回的必须还是迭代器
  2. 迭代器:实现迭代器协议的对象就叫迭代器
  3. 生成器:生成器可以理解为 生成迭代器的工厂,一种工厂函数(没找到好的定义),生成器的返回结果在Python中被称为 生成器迭代器 也是一种迭代器,也可以说迭代器包含着生成器,在Python3.6的文档(6.2.9. Yield expressions)中的原话是:When a generator function is called, it returns an iterator known as a generator.翻译一下大概是:当一个生成器函数被调用的时候,它返回一个称为生成器的迭代器(生成器迭代器)。
  4. 可迭代对象:能生成迭代器的对象,通俗的将也就是实现_iter_()方法的对象,以字符串举例 字符串可以进行迭代,但不能使用next(str),是因为字符串是可迭代对象而不是迭代器,也就是说字符串对象只实现了_iter_()方法而没有_next_()方法
    三者之间的关系如下:
    在这里插入图片描述

Demo 实现python3.6中的range方法

这里只是效果等同,不是复现

  1. 构建迭代器类:
class DemoIterator(object):

    def __init__(self, i, end):
        self.__i = i
        self.__end = end

    def __next__(self):
        if self.__i > self.__end:
            raise StopIteration()

        self.__i += 1
        return self.__i - 1

    def __iter__(self):
        # 由于这个方法要返回可迭代对象,他自己刚好就是
        return self
  1. 构建可迭代对象类
class DemoRange:

    def __init__(self, start, end):
        self.__start = start
        self.__end = end

    def __iter__(self):
        return DemoIterator(self.__start, self.__end)
  
if __name__ == '__main__':
    c = iter(DemoRange(0, 3))
    print("is_iterator:", isinstance(c, abc.Iterable))
    # 为了便于理解迭代器的工作流程下面用while 循环代替 for i in xx
    # for i in DemoRange(0, 3):
    #     print(i)
    # 可以看到for 循环为我们做了很多事情
    while True:
        try:
            print(next(c))
        except StopIteration:
            break

这里之所以不使用一个类实现是参考了《流畅的Python》一书中特意指出的不要 反设计
输出如下:

改进:使用生成器代替上述代码中的迭代器类

class DemoRange:

    def __init__(self, start, end):
        self.__start = start
        self.__end = end

    def __iter__(self):
        while True:
            if self.__start < self.__end:
                yield self.__start
                self.__start += 1
            else:
                raise StopIteration()
        # return DemoIterator(self.__start, self.__end)

这里可以看到省略了很多代码

总结

  1. 生成器和迭代器之间的区别还有生成器有 send(), throw(),close()等方法,见生成器方法这些方法刚好可以构成流程控制,比如使用 next() 激活一个生成器函数,通过何时使用send()控制生成器返回迭代器,next()得到结果来实现流程控制,而流程控制刚好又是协程的核心思想,于是各种yield实现协程的教程应运而生。而在早期版本中通常使用装饰器激活协程…扯远了
    转载注明出处
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值