10000000
个 `namedtuple` 实例占用了约850 MiB
的 RAM10000000
个 `tuple` 实例占用了约73 MiB
的 RAM10000000
个 `dict` 实例占用了约570 MiB
的 RAM
您认为呢? 我哪里做错了吗?
10000000
个 `namedtuple` 实例占用了约 850 MiB
的 RAM10000000
个 `tuple` 实例占用了约 73 MiB
的 RAM10000000
个 `dict` 实例占用了约 570 MiB
的 RAM一个更简单的度量方法是检查等价的tuple
和namedtuple
对象的大小。 给定两个大致类似的对象:
一个更简单的度量方法是检查等价的tuple
和namedtuple
对象的大小。给定两个大致类似的对象:
from collections import namedtuple
import sys
point = namedtuple('point', 'x y z')
point1 = point(1, 2, 3)
point2 = (1, 2, 3)
获取它们在内存中的大小:
>>> sys.getsizeof(point1)
72
>>> sys.getsizeof(point2)
72
在我看来它们看起来一模一样...
进一步地,为了重现您的结果,请注意,如果按照您所做的方式创建一个相同元组的列表,则每个元组
都是完全相同的对象:
>>> test_list = [(1,2,3) for _ in range(10000000)]
>>> test_list[0] is test_list[-1]
True
所以在你的元组列表中,每个索引都包含对相同对象的引用。这里没有10000000个元组,而是10000000个对同一元组的引用。
另一方面,你的namedtuple对象列表实际上创建了10000000个独立的对象。
一个更好的可比较的方式是查看内存使用情况
>>> test_list = [(i, i+1, i+2) for i in range(10000000)]
并且:
>>> test_list_n = [point(x=i, y=i+1, z=i+2) for i in range(10000000)]
它们大小相同:
>>> sys.getsizeof(test_list)
81528056
>>> sys.getsizeof(test_list_n)
81528056
>>> test_list_d = [{"x":i, "y":i+1, "z":i+2} for i in range(10000000)]
>>> sys.getsizeof(test_list_d)
81528056
- tekumara我用Python 3.6.6做了一些调查,得出以下结论:
在这三种情况下(元组列表、命名元组列表、字典列表),sys.getsizeof返回存储引用的列表的大小。所以在所有三种情况下,您都会得到大小:81528056。
基本类型的大小如下:
sys.getsizeof((1,2,3))
72
sys.getsizeof(point(x=1, y=2, z=3))
72
sys.getsizeof(dict(x=1, y=2, z=3))
240
命名元组的 timing 非常糟糕:
元组列表:1.8秒
命名元组列表:10秒
字典列表:4.6秒
查看系统负载后,我对 getsizeof 的结果产生了怀疑。
在测量 Python3 进程的占用内存时,我得出了以下结论:
test_list = [(i, i+1, i+2) for i in range(10000000)]
增加了:1 745 564K
每个元素约为 175B。
test_list_n = [point(x=i, y=i+1, z=i+2) for i in range(10000000)]
增加了:1 830 740K
每个元素约为 183B。
test_list_n = [point(x=i, y=i+1, z=i+2) for i in range(10000000)]
增加了:2 717 492 K
每个元素约为 272B。
namedtuple()
返回的类具有一些Python级别的属性,而dict
仍然是纯C的。 - Ashwini Chaudharyverbose=True
传递给构造函数,您可以查看用于生成命名元组的代码...所有属性都在类级别上定义--而且无论创建多少个实例,都只有一个类... - mgilson(1, 2, 3)
的构造被常量折叠,循环中的所有append
调用都将附加相同的元组。 - user2357112