【Python】生成器
生成器是一种特殊的迭代器
# 斐波那契数列 10
def create_num(all_num):
a, b = 0, 1
current_num = 0
while current_num < all_num:
# print(a)
yield a # 如果一个函数中有yield语句,那么这个就不在是函数,而是一个生成器的模板
a, b = b, a+b
current_num += 1
# 调用的时候,发现有yield,不是调用函数,是创建一个生成器对象
obj = create_num(10)
for i in obj:
print(i)
# send
def create_num(all_num):
a, b = 0, 1
current_num = 0
while current_num < all_num:
ret = yield a
print(">>>ret>>>", ret)
a, b = b, b+a
current_num ++ 1
obj = create_num(10)
# obj.send(None) # send一般不会放到第一次启动生成器,如果非要这样做 那么传递None
ret = next(obj)
print(ret)
# send里面的数据会 传递给第5行,当作yield a 的结果,然后ret保存这个结果...
# send的结果是下一次调用yield时,yield后面的值
ret = obj.send("haha")
print(ret)
yield 实现多任务, 协程
# 协程,调用任务就像调用函数一样,使用资源最少(进程 > 线程 > 协程)
import time
def task_1():
while True:
print("---1---")
time.sleep(0.1)
yield
def task_2():
while True:
print("---2---")
time.sleep(0.1)
yield
def main():
t1 = task_1()
t2 = task_2()
while True:
next(t1)
next(t2)
if __name__ == '__main__':
main()
## greenlet
# 安装
pip install greenlet
from greenlet import greenlet
import time
def test1():
while True:
print("---a---")
gr2.switch()
time.sleep(0.5)
def test2():
while True:
print("bbbb")
gr1.switch()
time.sleep(0.5)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
gevent的使用
# pip install gevent
import gevent
import time
# 遇到耗时等待,自动切换任务
from gevent import monkey
monkey.patch_all() # 耗时操作不用修改,可以使用 time.sleep 完成耗时,而非 gevent.sleep
def f1(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0.5)
# gevent.sleep(0.5)
def f2(n):
for i in range(n):
print(gevent.getcurrent(), i)
gevent.sleep(0.5) # gevent 的耗时操作
def f3(n):
for i in range(n):
print(gevent.getcurrent(), i)
gevent.sleep(0.5)
# g1 = gevent.spawn(f1, 5)
# g2 = gevent.spawn(f2, 5)
# g3 = gevent.spawn(f3, 5)
#
# g1.join()
# g2.join()
# g3.join()
gevent.joinall([
gevent.spawn(f1, 5),
gevent.spawn(f2, 5),
gevent.spawn(f3, 5)
])
gevent 怎么用?
from gevent import monkey
import gevent
import random
import time
# 有耗时操作时需要
monkey.patch_all() # 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
def coroutine_work(coroutine_name):
for i in range(10):
print(coroutine_name, i)
time.sleep(random.random())
gevent.joinall([
gevent.spawn(coroutine_work, "work1"),
gevent.spawn(coroutine_work, "work2")
])
协程图片下载器
import urllib.request
import gevent
from gevent import monkey
monkey.patch_all()
def downloader(url, name):
req = urllib.request.urlopen(url)
img_content = req.read()
with open(name, "wb") as f:
f.write(img_content)
def main():
gevent.joinall([
gevent.spawn(downloader, "https://rpic.douyucdn.cn/asrpic/191118/1554733_6854945_7c3f7_2_1502.jpg/webpdy1", "1.jpg"),
gevent.spawn(downloader, "https://rpic.douyucdn.cn/asrpic/191118/1282190_3853457_1abda_2_1450.jpg/webpdy1", "2.jpg")
])
if __name__ == '__main__':
main()