Reputation:
I just ran these codes:
v = [1,2,'kite',100**100]
for x,y in enumerate(v):
print ("{} size is: {}".format(y,sys.getsizeof(v[x])))
print ("Total size is: {} ".format(sys.getsizeof(v)))
Output:
1 size is: 14
2 size is: 14
kite size is: 29
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 size is: 102
Total size is: 52
>>>
The last element of v's size is 102, and total size is 52? Also even without the last element, still sum of the first 3 elements of the list is bigger than total size, my question is why? Python doing a zip process in lists ?
Another strange thing is, between this outputs;
v = [""]
for x,y in enumerate(v):
print ("{} size is: {}".format(y,sys.getsizeof(v[x])))
print ("Total size is: {} ".format(sys.getsizeof(v)))
v=[" "]
for x,y in enumerate(v):
print ("{} size is: {}".format(y,sys.getsizeof(v[x])))
print ("Total size is: {} ".format(sys.getsizeof(v)))
Output:
>>>
size is: 27
Total size is: 40
size is: 26
Total size is: 40
>>>
It is really strange, can anyone explain what's going on?
Upvotes: 2
Views: 2028
Reputation: 882606
From the documentation (my bold) (a):
Only the memory consumption directly attributed to the object is accounted for, not the memory consumption of objects it refers to.
So the size of v
does not include the sizes of the elements it refers to.
If you change kite
into kites
, you'll also see that its size increases but not the size of v
(I've replaced your big number with 100...00
in the output to ease formatting):
1 size is: 12
2 size is: 12
kite size is: 25
100...00 size is: 102
Total size is: 48
1 size is: 12
2 size is: 12
kites size is: 26
100...00 size is: 102
Total size is: 48
Think of it like this:
/ +-----+
| v | ref | -> 1
Size | | ref | -> 2
of v | | ref | -> 'kite'
| | ref | -> 100**100
\ +-----+
\___________________________/
Size of things referred
to by v
(a) That page also has a link to a recipe for doing recursive size calculations if you need that information. The link is duplicated here for citation, and the code is duplicated below to make this answer more self-contained.
Plugging your structure into that code gives:
48 <type 'list'> [1, 2, 'kites', 100...00L]
12 <type 'int'> 1
12 <type 'int'> 2
26 <type 'str'> 'kites'
102 <type 'long'> 100...00L
200
The code, with your structure, is shown below.
from __future__ import print_function
from sys import getsizeof, stderr
from itertools import chain
from collections import deque
try:
from reprlib import repr
except ImportError:
pass
def total_size(o, handlers={}, verbose=False):
""" Returns the approximate memory footprint an object and all of its contents.
Automatically finds the contents of the following builtin containers and
their subclasses: tuple, list, deque, dict, set and frozenset.
To search other containers, add handlers to iterate over their contents:
handlers = {SomeContainerClass: iter,
OtherContainerClass: OtherContainerClass.get_elements}
"""
dict_handler = lambda d: chain.from_iterable(d.items())
all_handlers = {tuple: iter,
list: iter,
deque: iter,
dict: dict_handler,
set: iter,
frozenset: iter,
}
all_handlers.update(handlers) # user handlers take precedence
seen = set() # track which object id's have already been seen
default_size = getsizeof(0) # estimate sizeof object without __sizeof__
def sizeof(o):
if id(o) in seen: # do not double count the same object
return 0
seen.add(id(o))
s = getsizeof(o, default_size)
if verbose:
print(s, type(o), repr(o), file=stderr)
for typ, handler in all_handlers.items():
if isinstance(o, typ):
s += sum(map(sizeof, handler(o)))
break
return s
return sizeof(o)
##### Example call #####
if __name__ == '__main__':
v = [1,2,'kites',100**100]
print(total_size(v, verbose=True))
Upvotes: 3
Reputation: 249592
This happens because your "Total size" is actually the size of the list structure without the contents. So you can store an object of any size there and it won't change your "Total size." You need a "recursive" getsizeof(), and for that, see here: Python deep getsizeof list with contents? or here: Deep version of sys.getsizeof
Upvotes: 1