美文网首页
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