协程笔记
2021-08-10 本文已影响0人
眼君
概念
并发与并行
- 并发:指一个时间段内,有几个程序在同一个cpu上运行,但是任意时刻只有一个程序在cpu上运行。
- 并行:指任意时刻,有多个程序同时在多个cpu上运行。
同步与异步
- 同步:指代码调用IO操作时,必须等待IO操作完成才返回的调用方式。
- 异步:指代码调用IO操作时,不必等IO操作完成就返回的调用方式。
协程解决的问题
- 一、采用同步的方式去编写异步的代码。
- 二、使用单线程去切换任务:
1、线程是由操作系统切换的,单线程切换意味着需要程序员自己去调度任务。2、不需要锁,并发性高,如果单线程内切换函数,性能远高于线程切换,并发性更高。
协程的定义
协程指可以暂停的函数,可以向暂停的地方传入值。
生成器的高级方法
send用法
启动生成器的方式有两种,分别是next和send,其中next可以获取生成器yield后面的值,send则可以向生成器内部传值。
1、send在向生成器内部传值的同时,也可以接受生成器返回的值,同时将生成器的代码执行到下一个yield。
def gen_func():
html = yield "http://www.baidu.com"
print(html)
yield 2
if __name__ == "__main__":
#生成器初始化
gen = gen_func()
url = next(gen)
html = "hello world !"
res = gen.send(html)
print(res)
打印结果如下:
hello world !
2
Process finished with exit code 0
2、在调用send发送非none信息时,必须启动生成器,将生成器指针移动到第一个yield的位置。
def gen_func():
html = yield "http://www.baidu.com"
print(html)
yield 2
if __name__ == "__main__":
#生成器初始化
gen = gen_func()
#url = next(gen)
html = "hello world !"
res = gen.send(html)
print(res)
上述未启动生成器,直接传非None值,直接报以下错误:
TypeError: can't send non-None value to a just-started generator
Process finished with exit code 1
以下代码先传None值,在传非None值则没有问题:
def gen_func():
html = yield "http://www.baidu.com"
print(html)
yield 2
if __name__ == "__main__":
#生成器初始化
gen = gen_func()
gen.send(None)
html = "hello world !"
res = gen.send(html)
print(res)
除了传None,也可以通过调用一次next方法来启动生成器。
close方法
close方法可以用来关闭生成器
def gen_func():
html = yield "http://www.baidu.com"
print(html)
yield 2
yield 3
return "ccc"
if __name__ == "__main__":
#生成器初始化
gen = gen_func()
print(next(gen))
gen.close()
next(gen)
上述代码在执行close关闭生成器后,继续执行next,结果报错:
StopIteration
Process finished with exit code 1
throw方法
throw方法可以向生成器中传入异常。
yield from 方法
1、yield from后面可以接一个可迭代对象:
my_list = [1,2,3,4,5,6,7]
def gen_func():
yield from my_list
if __name__ == "__main__":
gen = gen_func()
print(next(gen))
print(next(gen))
print(next(gen))
执行结果如下:
1
2
3
Process finished with exit code 0
由于生成器也是可迭代对象,yield from可以在调用方与子生成器之间建立一个双向通道,以下代码为例:
def g1(gen):
yield from gen
def main():
g = g1()
g.send(None)
其中函数main调用方,g1是委托生成器,gen是子生成器。
async和await
python3.5以后,为了将语义变得更加明确,就引入了async和await关键词用于定义原生的协程。
async和await可以替换yield from的语法:
def downloader(url):
return "xxx"
def download_url(url):
html = yield from downloader(url)
return html
可以写成:
async def downloader(url):
return "xxx"
async def download_url(url):
html = await downloader(url)
return html