许多过去在 Python 2.x 中返回列表的方法现在似乎在 Py3k 中返回迭代器
迭代器也是生成器表达式吗?懒惰的评价?
因此,有了这个,python 的内存占用将大大减少。不是吗?
使用内置脚本从 2to3 转换的程序呢?
为了兼容性,内置工具是否将所有返回的迭代器显式转换为列表?如果是这样,那么 Py3k 的较低内存占用优势在转换后的程序中并不明显。是吗?
许多过去在 Python 2.x 中返回列表的方法现在似乎在 Py3k 中返回迭代器
迭代器也是生成器表达式吗?懒惰的评价?
因此,有了这个,python 的内存占用将大大减少。不是吗?
使用内置脚本从 2to3 转换的程序呢?
为了兼容性,内置工具是否将所有返回的迭代器显式转换为列表?如果是这样,那么 Py3k 的较低内存占用优势在转换后的程序中并不明显。是吗?
其中许多并不完全是迭代器,而是特殊的视图对象。例如 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 中的真实列表对象。
迭代器也是生成器表达式吗?懒惰的评价?
迭代器只是一个带有 next 方法的对象。大多数时候,当说函数返回迭代器时,文档的意思是它的结果是延迟加载的。
因此,有了这个,python 的内存占用将大大减少。不是吗?
这取决于。我猜想普通程序不会注意到巨大的差异。只有当您拥有大型数据集时,迭代器相对于列表的性能优势才真正显着。你可能想看看这个问题。
迭代器相对于列表的最大好处之一不是内存,而是计算时间。例如,在 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 中的更多地方是默认的;您什么都没有,因为您仍然可以在需要时显式创建列表(或其他容器)。但是,当您计划做的只是迭代一个可迭代的一次(我认为这是更常见的情况)时,您不会被迫这样做。