欢迎访问宙启技术站
智能推送

Python中的生成器函数:co-routines和yield的使用技巧

发布时间:2023-06-21 20:48:49

生成器函数是 Python 中非常强大的概念。相较于普通函数,生成器函数能够实现的更多。在 Python 2 中,生成器函数使用 yield 语句来实现,而在 Python 3 中,支持使用 asyncio 库来实现协程(co-routines),并添加了新的语法来简化生成器函数的编写。本文将向您介绍 Python 中的生成器函数、协程(co-routines)以及 yield 和 async/await 语法的使用技巧。

## 什么是生成器函数?

生成器函数是一个可以返回一个迭代器的函数。它生成的迭代器可以用来实现惰性求值,即在需要的时候才计算值。在 Python 中,生成器函数是实现协程(co-routines)的基础,因此掌握生成器函数是编写异步代码的必备技能。

## 如何使用 yield 来实现生成器函数?

使用 Python 2 版本的话,您可以使用 yield 语句来实现生成器函数。下面是一个使用 yield 的示例:

def fibonacci(n):
    a, b = 0, 1
    while n > 0:
        yield b
        a, b = b, a+b
        n -= 1

这个函数接收一个参数 n,返回斐波那契数列的前 n 项。使用 yield 可以让函数返回一个迭代器,从而实现惰性求值。

接下来,我们可以使用 for 循环来遍历迭代器并打印出结果:

for i, fib_num in enumerate(fibonacci(10)):
    print "Fibonacci number %d is: %d" % (i+1, fib_num)

这段代码将会输出斐波那契数列的前 10 项。

## 如何使用 async/await 来实现协程(co-routines)?

在 Python 3 中,支持使用 asyncio 库来实现协程(co-routines),并添加了新的语法来简化生成器函数的编写。

下面是一个使用 asyncawait 语法来实现协程(co-routines)的示例:

import asyncio

async def foo():
    print('Start foo')
    await asyncio.sleep(1)
    print('End foo')

async def main():
    print('Start main')
    fut = asyncio.ensure_future(foo())
    await asyncio.sleep(0.5)
    print('Middle main')
    await fut
    print('End main')

asyncio.run(main())

在这个示例中,我们使用 asyncawait 语法来定义一个协程(co-routines)。协程(co-routines)是一种可以调度执行的函数,它可以在某些时候挂起执行,并在稍后继续执行。

在这个示例中,我们定义了一个名为 foo() 的协程(co-routines),该协程(co-routines)会输出 'Start foo',然后调用 asyncio.sleep(1) 来模拟执行时间,最后输出 'End foo'。

接下来,我们定义了另一个名为 main() 的协程(co-routines),该协程(co-routines)会输出 'Start main',然后使用 asyncio.ensure_future() 来创建一个 future 对象,用于执行 foo() 协程(co-routines)。

接着,我们使用 await asyncio.sleep(0.5) 来模拟执行时间,然后输出 'Middle main'。最后,我们使用 await 来等待 foo() 协程(co-routines)执行完成,然后输出 'End main'。

## 如何同时使用 yieldasync/await 来实现生成器函数?

Python 中,使用 yieldasync/await 来实现生成器函数的方法是相同的。

下面是一个同时使用 yieldasync/await 来实现生成器函数的示例:

import asyncio

async def fibonacci_async(n):
    a, b = 0, 1
    while n > 0:
        yield b
        await asyncio.sleep(0.5)
        a, b = b, a+b
        n -= 1

async def main_async():
    async for i, fib_num in enumerate(fibonacci_async(10), 1):
        print(f"Fibonacci number {i} is: {fib_num}")
        await asyncio.sleep(1)

asyncio.run(main_async())

在这个示例中,我们定义了一个名为 fibonacci_async() 的生成器函数,该函数会输出斐波那契数列的前 n 项,并使用 await 来暂停执行。

接着,我们定义了另一个名为 main_async() 的协程(co-routines),该协程(co-routines)使用 async for 循环来遍历 fibonacci_async(10) 生成器函数生成的迭代器,并输出斐波那契数列的每一项。

注意,在这个示例中,我们使用了 await asyncio.sleep(0.5) 来模拟执行时间,并使用 await asyncio.sleep(1) 来让 main_async() 协程(co-routines)暂停一秒钟。

## 总结

在 Python 中,生成器函数和协程(co-routines)是非常强大的概念。借助于 yieldasync/await 语法,我们可以轻松编写出高效的、惰性求值的、异步的功能。

掌握生成器函数和协程(co-routines)是编写 Python 异步代码的基础,可以让您的代码更加高效和易于维护。