007-迭代器-生成器-协程

迭代器 :
    区分 : 可迭代 ---> 实现了__iter__() 的类
             可迭代对象 ---> 实现了 __iter__() 的类的实例
            迭代器(对象) ---> 实现了 __iter__() 和 __next__() 的类的实例
    作用 : 一个可以记住遍历的位置的对象,真正能够获取位置内容的是 next()
    如何自定义一个迭代器对象?
        要创建两个类,一个普通类,一个迭代器类,合起来就是迭代器对象
        定义一个普通类,在普通类中实现 __iter__(),--> 此时,普通类的对象就是可迭代的,但还不能通过 for 将数据一个一个取出来,因为迭代器只是记录了位置。接着,要想能够通过 for 循环取数据,还要在迭代器类中实现  __iter__() 和 __next__() ,魔法方法 next 才是获得数据的关键
    想要构造一个迭代器,就要实现它的 __next__(),但这还不够,Python 要求迭代器本身也是可迭代的,所以我们还要为迭代器实现 __iter__(),而 __iter__() 要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的 __iter__() 返回自身 (self) 即可
    为什么 __iter__() 要返回一个迭代器?
         (配合 for 使用解释)因为当 for 循环一个可迭代对象时,本质是先通过 iter() 获取可迭代对象的迭代器,而 iter() 方法实际上是调用了可迭代对象的 __iter__(),所以如果 __iter__() 不返回一个迭代器的话,iter() 就得不到对象的迭代器,那么 for 也得不到迭代器,没有迭代器,就不能调用迭代器的 next(),就取不了值
    for 循环的本质 : ① 当 for 循环的是一个可迭代对象时,先通过 iter() 获取其迭代器,再通过调用 next() 获取对象的值 (调用 next() 实际是调用了迭代器的 __next__())。② 当 for 循环的是一个迭代器时,直接通过 next()获取值

协程(本质是生成器) :
    作用 : 在不开辟线程的境况下,在单线程内同时进行多个任务(实际上是同一时刻只能运行一个,但是切换的很快),协程执行是有序的,主线程默认不会等待协程运行结束再退出,需要 joinall()
    用法 :
        ① 不使用框架 : 在函数内使用 yield 关键字      next(函数名())
        ② greenlet 框架 : g1 = greenlet(函数名1)      函数名1(): g2.switch()
                            g2 = greenlet(函数名2)      函数名2(): g1.switch()
                            g1.switch()
        ③ gevent 框架 : monkey.patch_all()
                           g1 = gevent.spwan(函数名1)
                           g2 = gevent.spwan(函数名2)
                           gevent.joinall([g1,g2])
            注意点 : 使用 gevent 时,导入的 time 模块格式必须为 import time
                                        from time import sleep 将不会让协程交替运行

原文地址:https://www.cnblogs.com/hhj-study-10years/p/8955593.html

时间: 2024-10-07 08:16:21

007-迭代器-生成器-协程的相关文章

10.迭代器/生成器/协程函数/列表生成器

迭代器为什么要用迭代器?小结:生成器为什么要使用生成器,什么是生成器?如何创建一个生成器举个栗子:斐波拉契数列用yield返回结果的执行流程作业代码以及注释:协程函数面向过程编程作业以及代码注解:典型范例以及代码解析:列表生成式生成器表达式作业和练习 迭代器 为什么要用迭代器? 提供了一种不依赖索引的取值方式,使一些不具有索引属性的对象也能遍历输出 相比列表,迭代器的惰性计算更加节约内存. 但是它无法有针对性地指定取某个值,并且只能向后取值. >>> from collections i

状态机/迭代器/LINQ/协程

状态机 有限状态机(Finite State Machine 或 Finite State Automata)是软件领域中一种重要的工具. 状态机允许一个对象在其内部状态改变时改变它的行为.对象内部状态决定行为方式,对象状态改变行为方式改变,这里强调内部状态. Command 模式是将命令请求封装成一个为对象,将不同的请求对象参数化以达到同样的调用执行不同的命令: State 模式是将对象的状态封装成一个对象,是在不同的状态下同样的调用执行不同的操作. 迭代器是一个典型的状态机例子,后续会讲解.

【Python】【控制流程】【生成器 | 协程 | 期物 | 任务】对比与联系

Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyncio 是并发(concurrency)的一种方式.对 Python 来说,并发还可以通过线程(threading)和多进程(multiprocessing)来实现. Asyncio 并不能带来真正的并行(parallelism).当然,因为 GIL(全局解释器锁)的存在,Python 的多线程也不

并发编程--协程

协程,又称为微线程,可以理解成可切换的函数,或生成器,协程中始终在单线程中执行,因此没有资源冲突问题,不需要锁机制.以下以菲波那切数列为例,加上自己的一些理解,稍微聊一下这个东西. 斐波那契数列的普通实现 一般的函数只能有一个返回值,return,且return后程序不再执行.如下: # 斐波那契数列的普通实现 def fib(n): res = [0] * n index = 0 a = 0 b = 1 while index < n: res[index] = b a, b = b, a+b

python 高性能编程之协程

用 greenlet 协程处理异步事件 自从 PyCon 2011 协程成为热点话题以来,我一直对此有着浓厚的兴趣.为了异步,我们曾使用多线程编程.然而线程在有着 GIL 的 Python 中带来的性能瓶颈和多线程编程的高出错风险,"协程 + 多进程"的组合渐渐被认为是未来发展的方向.技术容易更新,思维转变却需要一个过渡.我之前在异步事件处理方面已经习惯了回调 + 多线程的思维方式,转换到协程还非常的不适应.这几天我非常艰难地查阅了一些资料并思考,得出了一个可能并不可靠的总结.尽管这个

python基础----迭代器、生成器、协程函数

一.什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法) 3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象. 二,为什么要用迭代器 优点: 1:迭代器提供了一种不依赖于索引的取值方式,

迭代器--》生成器--》协程的关系与区别

1.迭代器(iterator) 是一个实现了迭代器协议的对象,python的一些内置数据类型(列表,数组,字符串,字典等)都可以通过for语句进行迭代,我们也可以自己创建一个容器,实现了迭代器协议,可以通过for,next方法进行迭代,在迭代的末尾,会引发stopIteration异常. 判断xxx_obj是否可以迭代 在第1步成立的前提下,调用 iter 函数得到 xxx_obj 对象的 __iter__ 方法的返回值 __iter__ 方法的返回值是一个迭代器 如果想要一个对象称为一个 可以

Python快速学习第十二天--生成器和协程

yield指令,可以暂停一个函数并返回中间结果.使用该指令的函数将保存执行环境,并且在必要时恢复. 生成器比迭代器更加强大也更加复杂,需要花点功夫好好理解贯通. 看下面一段代码: [python] view plain copy def gen(): for x in xrange(4): tmp = yield x if tmp == 'hello': print 'world' else: print str(tmp) 只要函数中包含yield关键字,该函数调用就是生成器对象. [pytho

生成器、协程(yield)

来自: https://en.wikipedia.org/wiki/Coroutine 生成器,也称为semicoroutines,[5]也是子程序的泛化,但比协同程序更受限制. 具体来说,虽然这两个都可以多次产生,暂停它们的执行并允许在多个入口点重新进入,但是它们的不同之处在于,协同程序可以控制在它们屈服之后执行继续的位置,而发生器不能,而是将控制转移回生成器的调用者 .[6] 也就是说,由于生成器主要用于简化迭代器的写入,所以生成器中的yield语句不指定要跳转到的协程,而是将值传递回父例程