python yield和yield from用法总结详解

1. 什么是 yield?

在 Python 里使用 yield 关键字可以将一个函数变成生成器,可以用来迭代遍历数据,避免一次性加载所有的数据到内存,可以帮助我们节省大量的内存,从而提高效率。

1.1 yield 示例

看下面的示例,通过 yield 可以迭代打印一个列表中的每一个元素。 示例代码如下:

def my_generator():

my_list = [1, 2, 3, 4, 5]

for i in my_list:

yield i

generator = my_generator()

for item in generator:

print(item)

上述代码将会依次输出 1, 2, 3, 4, 5 这5个数字。

2. yield from 是什么?

yield from 可以将一个生成器作为子生成器,将生成器的数据以及状态直接传递给主生成器,从而可以更简单的实现复杂的协程操作。 yield from 会在最内层的子生成器和最外层的主体程序之间建立一个双向通道,使得子生成器直接获得调用者(主生成器)的上下文并返回结果。

2.1 yield from 示例

下面的示例展示了如何使用 yield from 来简单的重构之前的生成器。

def my_sub_generator():

my_list = [1, 2, 3, 4, 5]

yield from my_list

def my_generator():

yield from my_sub_generator()

generator = my_generator()

for item in generator:

print(item)

运行上述代码会输出与之前同样的结果:1, 2, 3, 4, 5 。

3. yield 和 yield from 的区别

yield from 是在 Python 3.3 版本后才支持的操作,它主要用在协程中,可以方便地实现迭代器和生成器。而 yield 是 Python 中常见的操作,用于将函数变成生成器。 yield from 是 yield 的进一步封装,尤其在协程中的使用更方便。

3.1 两个语句的使用方式不同

yield 和 yield from 的使用方式不同。在使用 yield 时,需要使用 next() 方法获得下一个生成器(iterable)中的值;而使用 yield from 则需要直接迭代生成器,yield from 从这个生成器中获取值,直到该生成器终止。

3.2 yield 和 yield from 的运行效率不同

当使用 yield 语句时,需要创建一个生成器对象,将其保存在内存中,并为它分配一个堆栈。 yield 语句需要单独完成运行,然后在下一次调用时从上一次离开的位置继续运行,这样可能会导致一些效率问题。而 yield from 则直接将序列中的值传递到连续的函数调用中,没有阻塞堆栈的执行。因此,yield from 在效率上比 yield 更优秀。

3.3 yield 和 yield from 使用场景不同

yield 通常用于生成器的生成,在使用这个语句时,需要根据外部要求生成一个值,更换状态,从而迭代计算得出总的结果。而 yield from 则主要用在协程操作中,可以大大减少编写协程微线程时的代码量,并且使用起来更方便。

4. yield 和 yield from 的应用场景

yield 和 yield from 非常适合于处理大数据量的业务场景,可以避免一次性加载所有的数据到内存,而是通过生成器逐个迭代的处理数据。除此之外,它还经常用于网络编程中,处理异步操作、协程等。

4.1 yield 和 yield from 在协程中的应用

协程是一种微线程,可以在单线程空间中实现多个任务之间的交替运行。使用 yield from 可以让协程像普通的函数一样实现返回,使得代码更加简洁易懂。下面是一个使用协程的示例代码:

import asyncio

async def foo():

print("start")

await asyncio.sleep(1)

print("end")

async def bar():

await foo()

await foo()

loop = asyncio.get_event_loop()

loop.run_until_complete(bar())

loop.close()

运行上述代码,将会输出如下结果:

start

end

start

end

4.2 yield 和 yield from 在处理大数据量的应用

如果处理的数据量很大,可能会导致内存不足,使得程序崩溃。使用 yield 和 yield from 可以避免这种情况的发生,将数据分成 small pieces,逐步迭代处理,从而实现节约内存和提高程序效率的目的。 下面是一个处理大数据量的示例代码:

import os

path = '/path/to/your/large/dataset'

def read_large_file(path):

with open(path, 'r') as f:

while True:

data = f.read(1024)

if not data:

break

yield data

# 使用 yield from 逐个处理大文件

def process_large_file(path):

for piece in read_large_file(path):

yield from process_piece(piece)

def process_piece(piece):

# do something with piece of the data

pass

for processed_piece in process_large_file(path):

pass

运行上述代码可以将大文件逐个处理,从而避免了同时读取整个文件的情况。

5. 总结

通过本文的介绍,我们可以了解到:yield 和 yield from 都是 Python 中很重要的语句,它们可以用于实现迭代遍历数据,节约大量的内存,提高程序的效率,在协程和大数据量的处理中也有广泛的应用。但是,它们之间有着使用方式、运行效率和应用场景的差异,我们在使用的时候需要根据实际需求进行选择。

后端开发标签