2

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?

1

2 Answers 2

3

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)) 
Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments