8

我有中等数量的基础对象。

这些基础对象将被放入集合中,并且这些集合将被修改:排序、截断等。

不幸的是,n足够大,以至于内存消耗有点令人担忧,而且速度也越来越令人担忧。

我的理解是,元组的内存效率稍高一些,因为它们被删除了重复数据。

无论如何,我想知道 Python 2.6/2.7 中列表与元组的 cpu/内存权衡是什么。

4

7 回答 7

16

如果您有一个元组和一个具有相同元素的列表,则元组占用的空间更少。由于元组是不可变的,因此您无法对它们进行排序、添加等。我建议观看Alex Gaynor的这篇演讲,以快速了解何时在 Python 中选择何种数据结构。

更新:再想一想,您可能需要考虑优化对象的空间使用,例如,通过__slots__或使用namedtuple实例作为代理而不是实际对象。这可能会带来更大的节省,因为您拥有其中 N 个并且(大概)只有少数几个集合出现它们。namedtuple特别是超级棒;查看Raymond Hettinger 的演讲

于 2011-05-19T18:55:32.983 回答
9

正如其他人提到的那样,元组是不可变的。对元组(例如sorted(mytuple))进行排序会返回一个列表,然后您必须将其转换回一个元组。

要对元组进行排序(并将其保留为元组),您必须这样做:

mytuple = (3,2,1)
mysortedtuple = tuple(sorted(mytuple))

要对列表进行排序,您必须这样做:

mylist = [3,2,1]
mylist.sort()

因为你不是在铸造和重新铸造,在这种情况下,后者更有效。

除非你有充分的理由,否则不要纠结于在列表上使用元组。如果您需要排序的数据,元组不是要走的路,除非它们首先以这种方式创建。当元组包含的数据不变时,例如在运行时加载的配置设置或已经处理的数据,元组表现出色。

考虑到您提到您正在处理一个大型数据集,您可能希望通过列表和元组上的生成器和迭代器来查看使用函数式编程风格。这样,您就不会四处穿梭并创建新容器,而只是链接迭代操作以获得最终结果。

进一步阅读:

于 2011-05-19T19:05:10.063 回答
4

集合中基础对象的(平均、最小、最大)数量是多少?

元组被“重复数据删除”而列表不是?您认为“重复数据删除”在这种情况下意味着什么?

列表确实比元组占用更多的内存,因为额外的内存是在假设列表会增长的情况下分配的,并且您绝对不想每次执行 large_list.append() 时都重新分配内存。但是在 32 位机器上,额外列表元素的摊销成本是 4 字节的指针,N 字节的元素本身,不超过另外 4 字节的额外内存。N 是浮点数的 16 个字节。这意味着浮点数列表每个额外的浮点数最多占用 24 个字节,而元组则需要 20 个字节。N==100 的“基础对象”给出 108 与 104 的比较。如果在两个集合中引用基础对象,则 58 与 54。你的 N 有多大?

建议:将您的收藏保留为列表。专注于:

  • 确保您的基础对象是内存高效的

  • 尽可能使用生成器和 itertools 好东西而不是临时列表

  • 如果您无法避免临时列表,请确保立即将它们丢弃,不再需要它们,即不要等到创建方法返回;del尽快使用显式。

于 2011-05-27T22:50:06.723 回答
3

除了所有这些建议之外,您可能会发现numpy将满足您的需求。如果您的对象是 numpy 默认处理的对象(整数、本机 C 类型等),那么这将是理想的。您也可以使用带有自定义对象的 numpy 数组,但这可能比它的价值更多。

于 2011-05-27T20:50:04.143 回答
2

你不能以同样的方式使用它们。元组是不可变的,不支持追加、排序等(调用sorted元组会产生一个列表,等等)。元组与列表完全不同,因此任何性能比较都是没有意义的。

于 2011-05-19T18:55:36.663 回答
1

至少有两个现有问题与您的问题足够相似,因此答案(或其中的链接)可能对您有用。总结一下:让类型的特征(可变与不可变,异构与同质)而不是性能来指导您的决定,因为性能/效率差异很小。

Python中的列表和元组有什么区别?
Python 中的 List、Dictionary 和 Tuple 有什么区别?

于 2011-05-19T19:03:02.263 回答
1

您不能对不可变对象进行排序——即,在对元组进行排序时,您总是会创建一个新对象。

于 2011-05-19T18:54:38.473 回答