如何在python中确定对象的大小?
答案是"只使用sys.getsizeof"不是完全完整的答案。
这可以直接对内置对象进行操作,但是它并不考虑包含的内容,特别是数字和字符串。
Bytes type empty + scaling notes
24 int NA
28 long NA
37 str + 1 byte per additional character
52 unicode + 4 bytes per additional character
56 tuple + 8 bytes per additional item
72 list + 32 for first, 8 for each additional
232 set sixth item increases to 744; 22nd, 2280; 86th, 8424
280 dict sixth item increases to 1048; 22nd, 3352; 86th, 12568
64 class inst has a __dict__ attr, same scaling as dict above
16 __slots__ class with slots has no dict, seems to store in
mutable tuple-like structure.
120 func def doesn't include default args and other attrs
904 class def has a proxy __dict__ structure for class attrs
104 old class makes sense, less stuff, has real dict though.
)
为了覆盖大多数类型,我编写了这个递归函数来估计大多数python对象的大小:import sys
import numbers
import collections
def getsize(obj):
# recursive function to dig out sizes of member objects:
def inner(obj, _seen_ids = set()):
obj_id = id(obj)
if obj_id in _seen_ids:
return 0
_seen_ids.add(obj_id)
size = sys.getsizeof(obj)
if isinstance(obj, (basestring, numbers.Number, xrange)):
pass # bypass remaining control flow and return
elif isinstance(obj, (tuple, list, set, frozenset)):
size += sum(inner(i) for i in obj)
elif isinstance(obj, collections.Mapping) or hasattr(obj, 'iteritems'):
size += sum(inner(k) + inner(v) for k, v in obj.iteritems())
else:
attr = getattr(obj, '__dict__', None)
if attr is not None:
size += inner(attr)
return size
return inner(obj)
我随便测了测(其实应该对它进行单元测试):>>> getsize(['a', tuple('bcd'), Foo()])
344
>>> getsize(Foo())
16
>>> getsize(tuple('bcd'))
194
>>> getsize(['a', tuple('bcd'), Foo(), {'foo': 'bar', 'baz': 'bar'}])
752
>>> getsize({'foo': 'bar', 'baz': 'bar'})
400
>>> getsize({})
280
>>> getsize({'foo':'bar'})
360
>>> getsize('foo')
40
>>> class Bar():
... def baz():
... pass
>>> getsize(Bar())
352
>>> getsize(Bar().__dict__)
280
>>> sys.getsizeof(Bar())
72
>>> getsize(Bar.__dict__)
872
>>> sys.getsizeof(Bar.__dict__)
280
在类定义和函数定义上有点小问题,因为没有追踪它们的所有属性。