【问题标题】:Why is this longer list smaller than this shorter list?为什么这个较长的列表比这个较短的列表小?
【发布时间】:2019-12-11 18:00:47
【问题描述】:

为什么img_listcompressed 小,即使更小?

输入

print(sys.getsizeof(img_list[0:1]))
print(img_list[0:1])
print(sys.getsizeof(compressed[0:2]))
print(compressed[0:2])

print(sys.getsizeof(img_list))
print(sys.getsizeof(compressed))

img_arr = np.asanyarray(img)
print(img_arr.shape)

comp_arr = np.asarray(compressed)
print(comp_arr.shape)

输出

72
[[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [19, 19, 19], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]
80
[[12, [0, 0, 0]], [1, [19, 19, 19]]]

256
2536

(24, 24, 3)
(306, 2)

【问题讨论】:

  • 您还没有在此处显示您的列表长度。你能提供一个minimal reproducible example吗?
  • @Error-SyntacticalRemorse 我不认为这就是这里发生的事情。同样,OP 实际上并没有提供任一列表的len。我怀疑img_list实际上大约是compressed长度的1/10。
  • @Error-SyntacticalRemorse 但带有 slices 的示例是一致的,越小的内存占用越小。切片的长度分别为 1 和 2...
  • 我将提供完整列表
  • 我将它们转换为 numpy 数组并打印了它们的形状以进行说明

标签: python list memory jupyter-notebook sys


【解决方案1】:

sys.getsize() 是骗人的。它返回对象的大小;但是,它不考虑对象属性的大小。换句话说,它不会递归地遍历您正在获取大小的对象。最终你需要自己做:

import sys

l1 = [[[0, 0, 0], [0, 19, 19], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 13, 0], [0, 0, 0], [19, 19, 19], [110, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 12, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]

l2 = [[12, [0, 0, 0]], [1, [19, 19, 19]]]

def get_size(obj, seen=None):
    """Recursively finds size of objects"""
    size = sys.getsizeof(obj)
    if seen is None:
        seen = set()
    obj_id = id(obj)
    if obj_id in seen:
        return 0
    # Important mark as seen *before* entering recursion to gracefully handle
    # self-referential objects
    seen.add(obj_id)
    if isinstance(obj, dict):
        size += sum([get_size(v, seen) for v in obj.values()])
        size += sum([get_size(k, seen) for k in obj.keys()])
    elif hasattr(obj, '__dict__'):
        size += get_size(obj.__dict__, seen)
    elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)):
        size += sum([get_size(i, seen) for i in obj])
    return size
print(get_size(l1))
print(get_size(l2))

输出:

5280
564

参考:Measure the Real Size of Any Python Object

你所做的基本上是:

sys.getsizeof([[]])

sys.getsizeof([[], []]) # This is bigger

【讨论】:

  • 非常感谢,真的很有帮助
  • 我仍然有一些问题。当我通过函数运行它们时。当我运行img_arrcomp_arr 时,我得到582img_arr5484comp_arr 的结果。当我运行列表时,它们的大小几乎相同。我想这是正确的值,但我为什么要得到它们?
  • @DenFulaAnkungen 是否有可能您的数组中的多个元素指向同一个对象?像 a = [[0,0,0],[0,0,0],[0,0,0]] 将有 3 个不同的列表,它们恰好具有相同的元素,而 sub = [0,0,0]; b = [sub,sub,sub] 有 3 个对同一列表的引用,因此空间更少。
猜你喜欢
  • 1970-01-01
  • 2019-07-10
  • 1970-01-01
  • 2021-02-25
  • 2017-12-06
  • 1970-01-01
  • 2015-05-01
  • 1970-01-01
  • 2019-10-23
相关资源
最近更新 更多