【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()
posted @ 2019-11-13 15:38  小白一生  阅读(144)  评论(0编辑  收藏  举报