3

许多过去在 Python 2.x 中返回列表的方法现在似乎在 Py3k 中返回迭代器

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

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

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

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

4

3 回答 3

7

其中许多并不完全是迭代器,而是特殊的视图对象。例如 range() 现在返回类似于旧的 xrange 对象的东西——它仍然可以被索引,但会根据需要懒惰地构造整数。

类似地 dict.keys() 给出了一个 dict_keys 对象,实现了对 dict 的视图,而不是使用键的副本创建一个新列表。

这如何影响内存占用可能取决于程序。当然,除非你真的需要列表,否则更强调使用迭代器,而使用列表通常是 python2 中的默认情况。这将导致普通程序的内存效率可能更高。然而,真正节省大量资金的情况可能已经作为迭代器在 python2 程序中实现,因为真正大量的内存使用会脱颖而出,并且更有可能已经解决。(例如,文件迭代器已经比旧file.readlines()方法更节省内存)

转换是由 2to3 工具完成的,通常会将 range() 之类的东西转换为迭代器,它可以安全地确定不需要真正的列表,所以代码如下:

for x in range(10): print x

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

x = range(20)

将转换为:

x = list(range(20))

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

于 2009-03-31T16:27:59.560 回答
1

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

迭代器只是一个带有 next 方法的对象。大多数时候,当说函数返回迭代器时,文档的意思是它的结果是延迟加载的。

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

这取决于。我猜想普通程序不会注意到巨大的差异。只有当您拥有大型数据集时,迭代器相对于列表的性能优势才真正显着。你可能想看看这个问题

于 2009-03-31T16:39:11.030 回答
0

迭代器相对于列表的最大好处之一不是内存,而是计算时间。例如,在 Python 2 中:

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

现在举个例子:

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 中的更多地方是默认的;您什么都没有,因为您仍然可以在需要时显式创建列表(或其他容器)。但是,当您计划做的只是迭代一个可迭代的一次(我认为这是更常见的情况)时,您不会被迫这样做。

于 2015-02-20T23:21:10.167 回答