关于python:通过返回迭代器而不是列表来保护Py3k内存

Py3k memory conservation by returning iterators rather than lists

许多在python 2.x中用于返回列表的方法现在似乎在py3k中返回迭代器。

迭代器也是生成器表达式吗?懒惰的评价?

因此,有了这一点,Python的内存占用将大大减少。不是吗?

对于使用内置脚本从2to3转换的程序呢?

为了兼容性,内置工具是否显式地将所有返回的迭代器转换为列表?如果是这样,那么在转换后的程序中,py3k的低内存占用优势并不明显。它是?


它们中的许多并不完全是迭代器,而是特殊的视图对象。例如,range()现在返回类似于旧xrange对象的内容-它仍然可以被索引,但可以根据需要延迟构造整数。

类似地,dict.keys()提供了一个dict-keys对象来实现dict上的视图,而不是用键的副本创建一个新的列表。

这如何影响内存足迹可能取决于程序。当然,除非您确实需要列表,否则更强调使用迭代器,而在python2中使用列表通常是默认情况。这将使普通程序的内存效率更高。在python2程序中,可能已经实现了节省大量内存的情况,但是,真正大的内存使用率将非常突出,而且更可能已经得到解决。(例如,文件迭代器已经比旧的file.readlines()方法具有更高的内存效率)

转换是由2to3工具完成的,通常会将range()等内容转换为迭代器,在迭代器中它可以安全地确定不需要实际的列表,因此代码如下:

1
for x in range(10): print x

将切换到新的range()对象,不再创建列表,因此将获得减少的内存优势,但代码如下:

1
x = range(20)

将转换为:

1
x = list(range(20))

因为转换器不知道代码是否需要x中的真实列表对象。


Are iterators also generator expressions? Lazy evaluation?

迭代器只是具有下一个方法的对象。当一个函数返回一个迭代器时,文档通常意味着它的结果被延迟加载。

Thus, with this the memory footprint of python is going to reduce drastically. Isn't it?

视情况而定。不过,我想一般的程序不会注意到巨大的差异。只有在拥有大型数据集的情况下,迭代器相对于列表的性能优势才真正重要。你可能想看看这个问题。


迭代器相对于列表最大的好处之一是不占用内存,这实际上是计算时间。例如,在python 2中:

1
2
3
for i in range(1000000):  # spend a bunch of time making a big list
    if i == 0:
        break  # Building the list was a waste since we only looped once

现在举个例子:

1
2
3
for i in xrange(1000000):  # starts loop almost immediately
    if i == 0:
        break  # we did't waste time even if we break early

尽管这个例子是人为的,但用例不是这样的:循环常常在中途中断。构建一个完整的列表来只使用其中的一部分是浪费的,除非您打算多次使用它。如果是这样,您可以显式地构建一个列表:r = list(range(100))。这就是为什么迭代器在python 3中的更多地方是默认的;因为您仍然可以在需要的时候显式地创建列表(或其他容器),所以您什么都没有。但是当你计划要做的只是迭代一次一个iterable(我认为这是更常见的情况)时,你不会被强迫去做。