首页 > 解决方案 > 为什么腌制和加载非空列表会改变其大小?

问题描述

我正在查看腌制对象的大小,并注意到非空列表在取消腌制后会改变大小。它们增大了 24 个字节。空列表的大小保持不变。如果我在这里getsizeof使用该方法,那么它表明嵌套列表也会发生同样的情况,并且每个非空列表的大小会增加 24 个字节。

这种增长是如何发生的?

一个小例子:

import pickle
import sys

li = [1]    

with open('test.p', 'wb') as f:
    pickle.dump(li, f)
print (getsize(li), sys.getsizeof(li))

with open('test.p', 'rb') as f:
    li2 = pickle.load(f)
print (sys.getsizeof(li2))

标签: pythonpickle

解决方案


pickled s的重建过程与文字list的“从头开始构建”过程不同。list当你有一个文字list时,它会精确地调整它的初始大小。当它从 a 重建时pickle,它会创建一个空的list,然后在它们未腌制时一个接一个地附加,每次容量耗尽时都会发生过度分配。

append您会看到与手动构建的比较的大小差异list(因为出于所有实际目的,这也是 unpickling 所做的):

import pickle
import sys

literal = [1]
incremental = []
incremental.append(1)
pickled = pickle.loads(pickle.dumps(literal, -1))

print("Literal:", sys.getsizeof(literal))
print("Incremental:", sys.getsizeof(incremental))
print("Pickled:", sys.getsizeof(pickled))

在线尝试!

在 TIO 上产生:

Literal: 80
Incremental: 104
Pickled: 104

数字因解释器而异(我自己的 Python 版本有 64、88、88),但模式是一样的;过度分配(以实现O(1)摊销append成本)影响增量/pickle基于list构造,但不影响list文字。


推荐阅读