1、生成器:是一类特殊的迭代器。
1)创建生成器的方法1:只要把一个列表生成式的 [ ] 改成 ( ),对于生成器G,我们可以按照迭代器的使用方法来使用,即可以通过next()函数、for循环、list()等方法使用。
In [17]: G = ( x*2 for x in range(5))
In [18]: G
Out[18]: <generator object at 0x7f626c132db0>
2)创建生成器方法2:在使用生成器实现的方式中,我们将原本在迭代器__next__方法中实现的基本逻辑放到一个函数中来实现,将每次迭代返回数值的return换成yield,此时新定义的函数便不再是函数,而是一个生成器。简单来说:只要在def中有yield关键字的 就称为 生成器
总结
1)使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器)
2)yield关键字有两点作用:
a. 保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起
b. 将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用
3)可以使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数)
4)Python3中的生成器可以使用return返回最终运行的返回值,而Python2中的生成器不允许使用return返回一个返回值(即可以使用return从生成器中退出,但return后不能有任何表达式)。
2、使用send唤醒:除了可以使用next()函数来唤醒生成器继续执行外,还可以使用send()函数来唤醒执行。使用send()函数的一个好处是可以在唤醒的同时向断点处传入一个附加数据。
3、协程-yield:协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定。
简单实现协程
import time
def work1():
while True:
print("----work1—")
yield
time.sleep(0.5)
def work2():
while True:
print("----work2—")
yield
time.sleep(0.5)
def main():
w1 = work1()
w2 = work2()
while True:
next(w1)
next(w2)
if name == “main”:
main()
4、协程-greenlet(人工切换协程)
使用如下命令安装greenlet模块:
sudo pip3 install greenlet
#coding=utf-8
from greenlet import greenlet
import time
def test1():
while True:
print “—A–”
gr2.switch()
time.sleep(0.5)
def test2():
while True:
print “—B–”
gr1.switch()
time.sleep(0.5)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
#切换到gr1中运行
gr1.switch()
5、协程-gevent(自动切换协程)
安装
pip3 install gevent
1)gevent的使用
import gevent
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()
2)gevent切换执行
import gevent
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
#用来模拟一个耗时操作,注意不是time模块中的sleep
gevent.sleep(1)
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()
6、进程、线程、协程对比
简单总结
1)进程是资源分配的单位
2)线程是操作系统调度的单位
3)进程切换需要的资源很最大,效率很低
4)线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)
5)协程切换任务资源很小,效率高
6)多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发