python协程之yield和yield from实例详解

  • Post category:Python

Python协程之yield和yield from实例详解

Python协程是一种轻量级的并发编程技术,它可以在单线程中实现多任务并发执行。在Python中,协可以使用yield和yield from关键字实现。本文将为您详细讲解Python协程之yield和yield from的原理和使用方法,并提供两个示例说明。

yield关键字

在Python中,yield关键字可以将一个函数转换为一个生成器。当函数执行到yield语句时,它会暂停执行,并将yield后面的值返回给调用者。当生成器再次被调用时,它会从上次暂停的位置继续执行。以下是一个使用yield关键字实现协程的示例:

def coroutine():
    while True:
        value = yield
        print('Received:', value)

c = coroutine()
next(c) # 启动协程
c.send('Hello, World!') # 发送数据

在上的示例中,我们定义了一个coroutine()函数,它使用yield关键字实现了一个协程。在协程中,我们使用while循环和yield语句实现了一个无限循环。当协程被调用时,它会暂停执行等待调用者发送数据。当调用者发送数据时,协程会从yield语句处继续执行,并打印接收到的数据。

yield from关键字

在Python 3.3及以上版本中,yield from关键字可以用于简化协程的实现。yield from关键字可以将一个生成器嵌套在另一个生成器中,并将内部生成器的值返回给外部生成器。以下是一个使用yield from关键字实现协程的示例:

def sub_coroutine():
    while True:
        value = yield
        print('Sub coroutine received:', value)

def coroutine():
    yield from sub_coroutine()

c = coroutine()
next(c) # 启动协程
c.send('Hello, World!') # 发送数据

在上面的示例中,我们定义了一个sub_coroutine()函数和一个coroutine()函数。在sub_coroutine()函数中,我们使用yield关键字实现了一个协程。在coroutine()函数中,我们使用yield from关键字将sub_coroutine()函数嵌套在coroutine()函数中,并将sub_coroutine()函数的值返回给coroutine()函数。当coroutine()函数被调用时,它会启动sub_coroutine()函数,并等待调用者发送数据。当调用者发送数据时,数据会被传递给sub_coroutine()函数,并打印接收到的数据。

示例一

以下是一个使用yield关键字实现协程的示例,它可以计算斐波那契数列:

def fibonacci():
    a, b = 0, 1
    while True:
        value = yield b
        if value == 'reset':
            a, b = 0, 1
        else:
            a, b = b, a + b

f = fibonacci()
next(f) # 启动协程
print(f.send(None)) # 输出1
print(f.send(None)) # 输出1
print(f.send(None)) # 输出2
print(f.send(None)) # 输出3
print(f.send(None)) # 输出5
print(f.send('reset')) # 重置协程
print(f.send(None)) # 输出1
print(f.send(None)) # 输出1

在上面的示例中,我们定义了一个fibonacci()函数,它使用yield关键字实现了一个协程。在协程中,我们使用while循环和yield语句实现了一个无限循环。当协程被调用时,它会暂停执行,并等待调用者发送数据。当调用者发送数据时,协程会从yield语句处继续执行,并计算下一个斐波那契数。当调用者发送’reset’时,协程会重置计算。

示例二

以下是一个使用yield from关键字实现协程的示例,它可以读取多个文件的内容:

def read_file(filename):
    with open(filename, 'r') as f:
        while True:
            line = f.readline()
            if not line:
                break
            yield line.strip()

def read_files(filenames):
    for filename in filenames:
        yield from read_file(filename)

for line in read_files(['file1.txt', 'file2.txt', 'file3.txt']):
    print(line)

在上面的示例中,我们定义了一个read_file()函数和一个read_files()函数。在read_file()函数中,我们使用yield关键字实现了一个协程,它可以读取一个文件的内容。在read_files()函数中,我们使用yield from关键字将read_file()函数嵌套在read_files()函数中,并读取多个文件的内容。最后,我们使用for循环遍历read_files()函数的返回值,并打印读取到的内容。

总结

本文为您详细讲解了Python协程之yield和yield from的原理和使用方法,并提供了两个示例说明。通过学习本文,您可以更好地掌握Python中的协程编程技巧,提高自己的并发编程能力。