迭代器
可迭代对象:实现迭代器协议的对象,迭代器协议:对象实现了_iter()_和_next()_方法
在python中,可以通过isinstance()判断一个对象是否可以迭代
from collections import Iterable # 判断列表 print(isinstance([], Iterable)) # 判断元组 print(isinstance((), Iterable)) # 判断字典 print(isinstance({}, Iterable)) # 判断字符串 print(isinstance("", Iterable)) # 判断整数 print(isinstance(100, Iterable)) # 判断boolean print(isinstance(False, Iterable))
生成器
包含yield关键字的函数,也是一个迭代器,调用next()方法,yield:保持当前程序的执行状态
- yield关键字有两点作用:
- 保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起
- 将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用
- 可以使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数)
- 也可以使用send()函数来唤醒生成器,使用send()可以在唤醒的同事向断点出传入一个附加数据数据
协程
协程,又称微线程,单线程下的并发,是一种用户态的轻量级线程,由用户之间控制调度的
协程的本质就是在单线程下,由用户之间控制一个任务遇到IO阻塞了就切换另外一个任务去执行,以此来提升效率
在python中使用协程完成多任务,用greenlet模块对其封装,从而使得切换任务变的更加简单
安装方式:
sudo pip3 install greenlet
import greenlet import time def wotk(): while True: print("---A---") g2.switch() time.sleep(1) def work(): while True: print("---B---") g1.switch() time.sleep(2) if __name__ == '__main__': # 生成greelent对象 g1=greenlet.greenlet(run=wotk) g2=greenlet.greenlet(run=work) g1.switch() g2.switch()
gevent
greenlet已经实现了协程,但是这个还的人工切换,是不是觉得太麻烦了,不要捉急,python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent
安装:
pip3 install gevent
代码如下:
import gevent import time from gevent import monkey # 打补丁 def task(index): for i in range(3): print('任务%d----代码快%d,当前gevent对象名称:%s'%(index,i,str(gevent.getcurrent()))) time.sleep(1) if __name__ == '__main__': # 打补丁 monkey.patch_all() gevent.joinall([gevent.spawn(task,1), gevent.spawn(task, 2), gevent.spawn(task, 3)]) print("主线程执行的最后代码")
打印结果如下:
协程之并发下载器实现案例
import urllib.request from gevent import monkey import gevent import time # 网络数据下载实现 def download(url,file_name): # url:要下载数据的网站 # file_name:存储在本地的文件名 response=urllib.request.urlopen(url) # 保存文件 write_file=open("文件路径"+file_name,"wb") while True: content=response.read(4096) if content: write_file.write(content) else: break write_file.close() if __name__ == '__main__': # 打补丁 monkey.patch_all() start_time=time.time() url1="https://desk-fd.zol-img.com.cn/t_s960x600c5/g5/M00/02/00/ChMkJ1bKw0yIXFW5AAbUq3ToEXAAALG0wMHWJsABtTD684.jpg" url2="https://desk-fd.zol-img.com.cn/t_s960x600c5/g5/M00/0F/08/ChMkJlauzGuIDo5-AAmEKbHNhzwAAH89wIKvi8ACYRB721.jpg" url3="https://desk-fd.zol-img.com.cn/t_s960x600c5/g5/M00/05/0C/ChMkJ1l_JQ6IXG6dAAiAKWFIRycAAfSaADwC8oACIBB894.jpg" gevent.joinall([gevent.spawn(download,url1,"1.jpg"), gevent.spawn(download, url2, "2.jpg"), gevent.spawn(download, url3, "3.jpg")]) end_time=time.time() print("下载的时间为:{}".format(end_time-start_time))
打印结果如下: