• Python--协程


    生成器 g

    生成器generator以及yield表达式详解

    • ret = yield expression
    • next(g)
    • g.send(arg)
    • g.throw(Exception)
    • g.close()
    • return msg
    • StopIteration msg
    点击查看代码
    def my_generator(n):
        for i in range(n):
            temp = yield i
            print(f'我是{temp}')
    
    
    g = my_generator(5)
    
    print(next(g))  # 输出0
    print(next(g))  # 输出1
    # g.send(100)  # 本来输出2,但是传入新的值100,改为输出100
    print(g.send(100))
    print(next(g))  # 输出3
    print(next(g))  # 输出4
    
    '''
    0#第一次迭代
    ---------------------
    我是None
    1#第二次迭代
    ---------------------
    我是100#第三次迭代
    ---------------------
    我是None#第四次迭代
    3
    ---------------------
    我是None#第五次迭代
    4
    '''
    
    print('-------------------------')
    
    
    def my_generator2():
        try:
            yield 'a'
            yield 'b'
            yield 'c'
            yield 'd'
            yield 'e'
        except ValueError:
            print('触发“ValueError"了')
        except TypeError:
            print('触发“TypeError"了')
    
    
    g = my_generator2()
    print(next(g))
    print(next(g))
    print('-------------------------')
    print(g.throw(ValueError))
    print('-------------------------')
    print(next(g))
    print(next(g))
    print('-------------------------')
    print(g.throw(TypeError))
    print('-------------------------')
    print(next(g))
    
    print('-------------------------')
    
    
    def my_generator3():
        yield 1
        return 'return返回了'
        yield 2
    
    
    g = my_generator3()
    print(next(g))
    print(next(g))
    print(next(g))
    
    

    生成器状态

    使用yield关键字实现协程
    Python协程详解(一)

    • GEN_CREATED:等待执行
    • GEN_RUNNING:解释器执行
    • GEN_SUSPENDED:在yield表达式处暂停
    • GEN_CLOSED:执行结束
    点击查看代码
    import datetime
    from inspect import getgeneratorstate
    from time import sleep
    import threading
    
    
    def get_state(coro):
        while True:
            print(datetime.datetime.now(), "其他线程生成器状态:%s", getgeneratorstate(coro))
            sleep(1)
    
    
    def simple_coroutine():
        for i in range(3):
            print(datetime.datetime.now(), 'simple_coroutine', i+1)
            sleep(3)
            x = yield i + 1
    
    
    my_coro = simple_coroutine()
    print(datetime.datetime.now(), "生成器初始状态:%s" % getgeneratorstate(my_coro))
    t = threading.Thread(target=get_state, args=(my_coro,))
    t.setDaemon(True)
    t.start()
    first = next(my_coro)
    print(datetime.datetime.now(), 'simple_coroutine返回:', first)
    print(datetime.datetime.now(), '开始循环')
    for i in range(5):
        try:
            print(datetime.datetime.now(), 'simple_coroutine返回:', my_coro.send(i))
            print(datetime.datetime.now(), "主线程生成器初始状态:%s" % getgeneratorstate(my_coro))
    
        except StopIteration:
            print(datetime.datetime.now(), "生成器的值拉取完毕")
    print(datetime.datetime.now(), "生成器最后状态:%s" % getgeneratorstate(my_coro))
    
    ''' 输出结果:
    2021-10-09 17:23:44.376290 生成器初始状态:GEN_CREATED
    2021-10-09 17:23:44.378290 其他线程生成器状态:%s GEN_CREATED
    2021-10-09 17:23:44.379277 simple_coroutine 1
    2021-10-09 17:23:45.389752 其他线程生成器状态:%s GEN_RUNNING
    2021-10-09 17:23:46.396555 其他线程生成器状态:%s GEN_RUNNING
    2021-10-09 17:23:47.393188 simple_coroutine返回: 1
    2021-10-09 17:23:47.393188 开始循环
    2021-10-09 17:23:47.393188 simple_coroutine 2
    2021-10-09 17:23:47.409192 其他线程生成器状态:%s GEN_RUNNING
    2021-10-09 17:23:48.419401 其他线程生成器状态:%s GEN_RUNNING
    2021-10-09 17:23:49.428855 其他线程生成器状态:%s GEN_RUNNING
    2021-10-09 17:23:47.393188 simple_coroutine返回: 2
    2021-10-09 17:23:50.406583 主线程生成器初始状态:GEN_SUSPENDED
    2021-10-09 17:23:50.406583 simple_coroutine 3
    2021-10-09 17:23:50.437131 其他线程生成器状态:%s GEN_RUNNING
    2021-10-09 17:23:51.448273 其他线程生成器状态:%s GEN_RUNNING
    2021-10-09 17:23:52.459059 其他线程生成器状态:%s GEN_RUNNING
    2021-10-09 17:23:50.406583 simple_coroutine返回: 3
    2021-10-09 17:23:53.408010 主线程生成器初始状态:GEN_SUSPENDED
    2021-10-09 17:23:53.408010 生成器的值拉取完毕
    2021-10-09 17:23:53.408010 生成器的值拉取完毕
    2021-10-09 17:23:53.408010 生成器的值拉取完毕
    2021-10-09 17:23:53.408010 生成器最后状态:GEN_CLOSED
    '''
    
    

    生成器实现协程

    使用yield关键字实现协程

    • 根据send传入的值,生成器可以返回不同的结果
    点击查看代码
    def consumer():
        r = ''
        while True:
            n = yield r  # 执行的中断点
            if not n:
                return
            print('[消费者] 正在消费:{0}'.format(n))
            r = f'{n * 100} 人民币'  # 根据send进来的值返回不同的结果
    
    
    def produce(c):
        c.send(None)  # 启动消费者(生成器)——实际上是函数调用,只不过生成器不是直接象函数那般调用的
        n = 0
        while n < 5:
            n = n + 1
            print('[生产者] 正在生产:{0}'.format(n))
            r = c.send(n)  # 给消费者传入值——实际上也是函数调用
            print('[生产者] 消费者返回:{0}'.format(r))
            print('-------------------------------------------------')
        c.close()
    
    
    c = consumer()  # 构造一个生成器
    produce(c)
    
    '''运行结果为:
    [生产者] 正在生产:1
    [消费者] 正在消费:1
    [生产者] 消费者返回:100 人民币
    -------------------------------------------------
    [生产者] 正在生产:2
    [消费者] 正在消费:2
    [生产者] 消费者返回:200 人民币
    -------------------------------------------------
    [生产者] 正在生产:3
    [消费者] 正在消费:3
    [生产者] 消费者返回:300 人民币
    -------------------------------------------------
    [生产者] 正在生产:4
    [消费者] 正在消费:4
    [生产者] 消费者返回:400 人民币
    -------------------------------------------------
    [生产者] 正在生产:5
    [消费者] 正在消费:5
    [生产者] 消费者返回:500 人民币
    -------------------------------------------------
    '''
    

    yield from

    yield from原理详解

    点击查看代码
    def my_generator():
        for i in range(5):
            if i == 3:
                return '我被迫中断了'
            else:
                yield i
    
    
    def wrap_my_generator(generator):  # 定义一个包装“生成器”的生成器,它的本质还是生成器
        result = yield from generator  # 自动触发StopIteration异常,并且将return的返回值赋值给yield from表达式的结果,即result
        print('wrap_my_generator', result)
    
    
    def main(generator):
        for j in generator:
            print('main', j)
    
    # def main(generator):
    #     print('main', next(generator))
    #     print('main', next(generator))
    #     # print('main', generator.throw(Exception('异常来了')))
    #     # print('main', generator.throw(StopIteration('异常来了')))
    #     print('main', next(generator))
    #     print('main', next(generator))
    #     print('main', next(generator))
    
    
    g = my_generator()
    wrap_g = wrap_my_generator(g)
    main(wrap_g)  # 调用
    '''运行结果为:
    main 0
    main 1
    main 2
    wrap_my_generator 我被迫中断了
    '''
    

    Asyncio

    asyncio的核心概念与基本架构

    1. coroutine(协程)
      • yield/yield from (3.5之前)
      • async/await (3.5及之后)
    2. event loop(事件循环)
      • loop = asyncio.get_running_loop() (3.7版本加)
      • loop = asyncio.get_event_loop()
      • loop = asyncio.new_event_loop()
      • asyncio.set_event_loop(loop)
      • 一个线程只能有一个event loop
    3. awaitable对象
      • coroutine、Task、Future
      • coroutine本质是一个函数,可自动封装成为Task,Task是Future的子类
    4. 创建任务
      • loop.create_task(coro) 将协程转Task
      • loop.create_future() 创建Future (这里是不是就把任务添加到事件循环里面了呢??)
      • asyncio.create_task(coro) (3.7版本加)
      • asyncio.ensure_future(coro_or_future) 当参数是coro时,函数里面调用的就是loop.create_task(coro) 3.5+版本参数coro_or_future可以是一个awaitable对象
    5. 多任务
      • done,pending = await asyncio.wait([task1, task2,...])
      • results = await asyncio.gather(*[task1, task2,...])
    6. 运行事件循环
      • loop.run_until_complete(asyncio.wait([task1, task2,...]))
      • loop.run_until_complete(asyncio.gather(*[task1, task2,...]))
      • loop.run_until_complete(task)
      • loop.run_forever()
      • asyncio.run() (3.7版本加)

    小例子

    点击查看代码
    import asyncio
    import random
    import sys
    from datetime import datetime
    
    
    # 3
    async def consumer():
        while True:
            item = await queue.get()
            print(datetime.now(), "I'm working hard", item)
            await asyncio.sleep(random.random() * 3)
    
    
    async def producer():
        while True:
            await queue.put(random.randint(0, sys.maxsize))
            print(datetime.now(), 'count:', queue.qsize())
            await asyncio.sleep(random.random() * 2)
    
    
    # 2
    # async def worker():
    #     print(datetime.now(), "I'm working hard")
    #
    #
    # async def main():
    #     while True:
    #         asyncio.ensure_future(worker())
    #         await asyncio.sleep(random.random() * 2)
    
    # 1
    # def main():
    #     asyncio.ensure_future(consumer())
    #     asyncio.ensure_future(producer())
    
    
    # 1 3
    queue = asyncio.Queue()
    # 1
    # main()
    loop = asyncio.get_event_loop()
    # 1
    # loop.run_forever()
    # 2
    # loop.run_until_complete(main())
    # 3
    loop.run_until_complete(asyncio.wait([consumer(), producer()]))
    
    
  • 相关阅读:
    JDK中的主要包
    package

    参数传值机制
    静态初始化块
    static 关键字
    this关键字
    开发中容易造成内存泄露的操作
    通用的分代垃圾回收机制
    JVM调优和Full GC
  • 原文地址:https://www.cnblogs.com/yarightok/p/15387128.html
Copyright © 2020-2023  润新知