请注意以下与解释器的交互:
>>> import sys
>>> array = ['this', 'is', 'a', 'string', 'array']
>>> sys.getsizeof(array)
56
>>> list(map(sys.getsizeof, array))
[29, 27, 26, 31, 30]
>>> sys.getsizeof(array) + sum(map(sys.getsizeof, array))
199
>>>
在这种特定情况下,答案是用于sys.getsizeof(array) + sum(map(sys.getsizeof, array))
查找字符串列表的大小。但是,以下将是一个更完整的实现,它考虑了对象容器、类和 __slots__ 的用法。
import sys
def sizeof(obj):
return _sizeof(obj, set())
def _sizeof(obj, memo):
# Add this object's size just once.
location = id(obj)
if location in memo:
return 0
memo.add(location)
total = sys.getsizeof(obj)
# Look for any class instance data.
try:
obj = vars(obj)
except TypeError:
pass
# Handle containers holding objects.
if isinstance(obj, (tuple, list, frozenset, set)):
for item in obj:
total += _sizeof(item, memo)
# Handle the two-sided nature of dicts.
elif isinstance(obj, dict):
for key, value in dict.items():
total += _sizeof(key, memo) + _sizeof(value, memo)
# Handle class instances using __slots__.
elif hasattr(obj, '__slots__'):
for key, value in ((name, getattr(obj, name))
for name in obj.__slots__ if hasattr(obj, name)):
total += _sizeof(key, memo) + _sizeof(value, memo)
return total
编辑:
一段时间后解决这个问题后,设计了以下替代方案。请注意,它不适用于无限迭代器。此代码最适合用于分析的静态数据结构。
import sys
sizeof = lambda obj: sum(map(sys.getsizeof, explore(obj, set())))
def explore(obj, memo):
loc = id(obj)
if loc not in memo:
memo.add(loc)
yield obj
# Handle instances with slots.
try:
slots = obj.__slots__
except AttributeError:
pass
else:
for name in slots:
try:
attr = getattr(obj, name)
except AttributeError:
pass
else:
yield from explore(attr, memo)
# Handle instances with dict.
try:
attrs = obj.__dict__
except AttributeError:
pass
else:
yield from explore(attrs, memo)
# Handle dicts or iterables.
for name in 'keys', 'values', '__iter__':
try:
attr = getattr(obj, name)
except AttributeError:
pass
else:
for item in attr():
yield from explore(item, memo)