美文网首页
Python中yield语法

Python中yield语法

作者: 愤愤的有痣青年 | 来源:发表于2020-05-11 11:06 被阅读0次

    本文参考自某乎

    yield在Python中是用来暂停并返回当前操作的一个语法,其可以使用场景来说一般有三类,分别是:

      1. 生成器
      1. 上下文管理器
      1. 协程
      1. 配合 from 形成 yield from 用于消费子生成器并传递消息

    其使用语法主要有四类:

    • yield 暂停当前位置
    • yield expr,暂停并返回expr
    • n = yield expr, 暂停返回expr,并接收send函数传过来的n
    • n = yidld from func(), func也是一个可迭代对象,此处是作用是将func对象作为当前的迭代数据.

    1. 生成器场景是使用

    最常见的例子,斐波那契数列算法

    def fib():
        a, b = 0, 1
        while True:
            yield b
            a, b = b, a + b
    
    b = fib()
    for i in range(10):
        print(next(b), end=' ')
    

    输出内容:

    1 1 2 3 5 8 13 21 34 55
    

    2.上下文管理器

    上下文可以用来管理一些需要进行'收尾'工作的代码,例如文件打开后需要关闭,数据库连接后需要关闭等,下面是演示数据库的场景,其中使用到了contextlib.contextmanager上下文管理模块

    
    import sqlite3
    from contextlib import contextmanager
    
    @contextmanager
    def connect():
        conn = sqlite3.connect('test.db')
        try:
            yield conn
        finally:
            print('close')
            conn.close()
    
    
    with connect() as conn:
        cur = conn.cursor()
        cur.execute('create table test(name varchar(10));')
        conn.commit()
    

    3. 协程

    如下有两个函数countdowncountup,在其需要切换的地方加上yield,当程序运行到此处时将会中断,这是TaskScheduler对象中的_task_queue属性将会保存当前中断的地方,然后运行下一个函数,这样使得countdowncountup得以交替运行.

    
    def countdown(n):
        while n > 0:
            print('T-minus', n)
            yield
            n -= 1
        print('Blastoff!')
    
    def countup(n):
        x = 0
        while x < n:
            print('Counting up', x)
            yield
            x += 1
    
    class TaskScheduler:
        def __init__(self):
            self._task_queue = []
    
        def new_task(self, task):
            '''
            Admit a newly started task to the scheduler
    
            '''
            self._task_queue.append(task)
    
        def run(self):
            '''
            Run until there are no more tasks
            '''
            while self._task_queue:
                task = self._task_queue.pop(0)
                try:
                    # Run until the next yield statement
                    next(task)
                    self._task_queue.append(task)
                except StopIteration:
                    # Generator is no longer executing
                    pass
    
    # Example use
    sched = TaskScheduler()
    sched.new_task(countdown(2))
    sched.new_task(countup(5))
    sched.run()
    

    输出如下

    T-minus 2
    Counting up 0
    T-minus 1
    Counting up 1
    Blastoff!
    Counting up 2
    Counting up 3
    Counting up 4
    
    • 上面的代码还可以用asyncio来代替,其中的asyncio.sleep(0)也是一个async 对象.
    import asyncio
    
    async def countdown(n):
        while n > 0:
            print('T-minus', n)
            await asyncio.sleep(0)
            n -= 1
        print('Blastoff!')
    
    async def countup(n):
        x = 0
        while x < n:
            print('Counting up', x)
            await asyncio.sleep(0)
            x += 1
    
    async def main():
        await asyncio.gather(countdown(2), countup(5))
    
    asyncio.run(main())
    

    4. 配合 from 形成 yield from 用于消费子生成器并传递消息

    下面示例用来输出字典,列表的数据.

    from collections.abc import Iterable
    
    
    def averager(params):
        if not isinstance(params, Iterable):
            params = [params]
        elif isinstance(params, dict):
            params = params.values()
    
        for param in params:
            if isinstance(param, Iterable):
                yield from averager(param)
            else:
                yield param
    
    
    params = [1, [2, 3], (4, 5), {"p1": 6, "p7": 7}]
    
    for param in averager(params):
        print(param, end=' ')
    

    输出内容

    1 2 3 4 5 6 7 
    

    相关文章

      网友评论

          本文标题:Python中yield语法

          本文链接:https://www.haomeiwen.com/subject/gobynhtx.html