Python_协程详解与线程、进程区别

在说协程前,需要先了解在Python中常用迭代器和生成器,了解这两个能够有效的帮助你去理解协程的工作原理

 

迭代

    概念:通过for循环遍历取值的过程叫迭代

    可迭代对象:可用for循环遍历取值的对象,[列表、元组、字典、集合、range、字符串]

    判断方式:

        导入:form collections import Iterable

        判断:result = isinstance(数据,Iterable[迭代对象类型])    【返回boole值】

    自定义迭代对象:

        在类中定义__iter__方法创建的对象

    注意:

        1.只要有__iter__方法的类创建的对象是可迭代对象,可迭代对象需要迭代器完成数据迭代

 

迭代器

    概念:在类里定义__iter__和__next__方法创建的对象就是迭代器对象

    迭代器作用:记录当前数据位置,便于获取下一个位置的数据

    优点:占用极小内存空间,存储的是生成数据的方式而不是结果

    实现: 延迟计算 / 懒惰计算

    判断方式:

        导入:from collections import Iterator

        判断:result = isinstance(数据,Iterator[迭代器对象类型]) 

    自定义迭代器

        iter()函数:获取可迭代对象的迭代器,调用可迭代对象的__iter__方法

        next()函数:获取迭代器中下一个值,会调用迭代器对象的__next__方法

        注意:

            1.迭代对象中的__iter__方法创建迭代器对象并返回

            2.迭代器通过__next__获取下一个数据,数据取完后需要手动抛出停止迭代的异常(raise StopIteration)

            3.循环通过迭代器获取数据时,需要进行异常捕获,避免程序停止报错

 

    for循环的本质

        遍历 可迭代对象

        运行流程:for item in Iterable

            1.通过 iter() 函数获取可迭代对象 Iterable 的迭代器

            2.对获取的迭代器不断调用 next() 方法获取下一个值并赋值给item

            3.当遇到 StopIteration 的异常后循环结束

        遍历 迭代器

        运行流程:for item in Iterator

            1.循环的迭代器不断调用 next() 方法获取下一个值赋值给item

            2.遇到Stoplteration异常结束循环

    应用场景:

        迭代器的核心功能是通过next()函数调用返回下一个数据值,如果数据来源不是已有的集合中,而是通过程序按照一定规律生成,那么可以不用依赖已有的数据集合,可以不用将所有要迭代的数据全部缓存后依次读取,可以节省大量的内存资源

    

生成器

    概念:不需要自己定义__iter__和__next__方法仍然可以使用next函数和for循环取值

    场景:保证代码只指定一部分就返回

    创建:

        1.生成器表达式:将列表表达式的 [ ]更改为 ()    【生成器存储的是算法,占用的内存更少】

        2.函数生成器:使用了yield关键字

            1.在yield下可以使用return,代码执行到return时,会停止迭代,抛出停止异常

            【Python3才支持 return 关键字,可以通过except StopIteration as e: 捕获 e.value 输出】

            两者之间区别:

                1.使用了 yield 关键字的函数就是生成器

                2.代码执行到yield会暂停挂起,将结果返回给调用生成器的位置,下次启动时从挂起位置继续

                3.每次启动生成器都会返回一个值,yield可以返回多个值    

                4.return只能返回一次值,代码执行return 停止迭代

                5.生成器的结束都是  StopIteration 异常抛出,所以需要提前设置好捕获

            2.使用send方法启动生成器传参

                异同:

                    next是函数send是方法

                    next不能传参send可以传参

                    第一次调用必须是next,后续可以是send<传递的参数在yield左边的变量获取

                    send执行时也是从yield位置开始>

        注意:

            1.单独获取生成器内容next(生成器对象)

            2.for循环遍历后,直接输出结果,不需要next()】

 

协程

    概念:  微线程、用户级线程,在def中有yield关键字就是协程 

    创建:

        1.greenlet

        【该类需要下载后导入,通过 greenlet.greenlet(方法名) 创建协程对象,对象.switch()进行调取方法,不过用的一般很少】

        2.gevent(常用)

        概述:内部封装了greenlet,遇到IO[input、output、网络、文件操作]操作时,自动切换其他的greenlet,操作完成,再切换回来继续执行

        应用:

            1.导入:from gevent import monkey

            2.执行补丁:monkey.patch_all()    【使gevent识别耗时操作异步执行处理,必须放在代码开始处,避免加载问题】

            3.创建协程对象:xx = gevent.spawn(方法名,位置参数(args),关键字参数(kwargs))

            4.等待执行完成:xx.join()    【如果当前是无限循环且有耗时操作,可以不需要join】

            5.批量进程等待:gevent.joinall([对象1],[对象2])

 

进程、线程、协程对比

    1.关联

        一个进程至少有一个线程,进程里面可以有多个线程

        一个线程里面可以 有多个协程

    2.对比

        1.进程是资源分配的基础单位

        2.线程是操作系统调度的基本单位

        3.进程切换需要的资源最大,效率很低

        4.线程切换需要的资源一般,效率一般(不基于GIL的情况下)

        5.线程切换任务资源很小,效率高

        6.多进程、多线程根据cpu核数不一样可能是并行,但是协程是一个线程中,所以是并发

        7.进程和线程都是由系统进行控制执行,而协程有程序员控制

        8.进程适用于CPU密集不需要切换,大量并发计算的情况

        9.多线程适用IO密集,网络IO和磁盘IO

        10.协程适用于:密集网络IO,适合网络IO

 

 

    

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值