您是否曾经处理过大到计算机内存无法处理的数据集?您是否想过是否有办法在中途中断某个函数然后再恢复它?这就是 Python 生成器发挥作用的地方。

Python 生成器是一种创建自定义迭代器的方法。您可以 在此处 信息。在继续之前,如果您不熟悉 Python 术语,请查看我们关于 初学者 Python 术语 和 更多 Python 术语的 。如果您不熟悉 Python 中数据结构的操作,您可能想尝试我们的 Python 内置算法 课程。

您可以像使用列表一样循环遍历生成器对象。但与列表不同,生成器不会将其内容存储在内存中。一个广泛的用例是当您必须处理大于机器内存可以处理的文件时,例如大型数据集。尝试打开这样的文件将导致 MemoryError .

通过使用 Python 生成器,您可以避免此类问题。但请稍等!如何定义 Python 生成器?

如何在 Python 中定义生成器

Python 生成器与常规 Python 函数非常相似,但我们用 yield return 关键字来结束它。让我们使用 for loop .

def regular_function(x):
    for i in range(x):
        return i*5

一旦执行 regular_function(10) ,这个常规函数将返回 0,因为执行在第一次迭代后停止。

但是,我们可以用稍微不同的方式来写:

def generator(x):
    for i in range(x):
        yield i*5

Python yield 关键字表示我们启动了一个生成器对象;它在这里控制 Python 生成器的流程。当程序到达它时,函数的执行将暂停,并 yield 返回来自的值。

此时,函数的状态已保存,只要您调用生成器的某个方法,函数就会恢复执行。语句 return 会完全停止该函数。

因此,当我们运行..

generator(10)

..我们得到:

接下来,我们将生成器对象实例化为 g

>>> g = generator(10)

要在 Python 中执行生成器,我们需要使用 next() 方法。在下面的示例中,我们包含 print statements 来获取一些输出:

>>> print(next(g))
0
>>> print(next(g))
5
>>> print(next(g))
10
>>> print(next(g))
15

虽然该 next() 方法特定于 Python 中的生成器,但它并不是 to pause or end a for loop .

在 Python 中定义生成器的另一种方法是使用生成器推导式。与列表推导式非常相似,生成器推导式可以定义为:

gen_comp = (i*5 for i in range(10))

列表推导 相比 ,生成器推导的优点在于,在迭代之前无需在内存中构建和保存整个对象。让我们将生成器组合与列表推导进行比较:

list_comp = [i*5 for i in range(100000)]
gen_comp = (i*5 for i in range(10000))

这些表达式看起来非常相似;唯一的区别是括号和圆括号。即便如此,它们实际上非常不同。让我们看看它们的大小:

>>> import sys 
>>> list_comp
>>> print('list comprehension:', sys.getsizeof(list_comp), 'bytes')
list comprehension: 87616 bytes
>>> gen_comp 
>>> print('generator comprehension:', sys.getsizeof(gen_comp), 'bytes')
generator comprehension: 112 bytes

在这种情况下,列表对象大约比生成器对象大 782 倍。因此,如果内存是一个问题,你最好使用 Python 生成器。

最后但并非最不重要的一点是,除了语法之外,常规生成器和生成器推导式之间没有区别。唯一的区别是生成器推导式是单行的。

如果出于某种原因需要定义无限循环,则需要使用 Python 生成器。虽然序列可以是无限的,但计算机的内存肯定不是无限的。

def infinity():
    n = 0
    while True:
        yield n*n
        n += 13

我们初始化一个变量 n 并启动一个无限循环。关键字 yield 将捕获初始状态并模仿 的操作 range() ;最后,我们将 n 13。该程序将继续 for 循环,直到我们手动停止它。

在我们的例子中,通过调用 next() ,我们可以手动反复迭代,这有助于测试生成器以确保它产生预期的输出。这是否意味着生成器可以无限期地继续运行?

如何在 Python 中结束生成器

首先,它可以自然停止。换句话说,一旦所有值都被评估,迭代就会停止,并且 for 循环将退出。

如果您使用 next() ,您将得到一个明确的 StopIteration 异常。

结束 Python 生成器的另一种方式是使用 close() 方法,如下所示:

>>> def generator(x):
...    for i in range(x):
...        yield i*5
>>> g = generator(10)

>>> print(next(g))
0
>>> print(next(g))
5
>>> print(g.close())
None

close() GeneratorExit 抛出一个 yield 异常并停止生成器的执行。它可以方便地控制无限生成器的流程。

关于 Python 中生成器的总结

在本文中,我们了解了 Python 中的生成器。我们发现了它们如何有助于处理内存密集型计算,以及如何为我们的函数提供更大的灵活性(例如,在测试输出时)。

我鼓励您进一步探索本文的示例,并查看 Python 文档 以获取更多信息。我们的 Python 基础课程 还可以帮助新程序员获得实际的编码经验。无需任何 IT 知识。

最后但同样重要的是,不要忘记查看我们在 。祝您学习愉快!

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部