您是否曾经处理过大到计算机内存无法处理的数据集?您是否想过是否有办法在中途中断某个函数然后再恢复它?这就是 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 知识。
最后但同样重要的是,不要忘记查看我们在 。祝您学习愉快!
发表评论 取消回复