2

I was just checking the size of some datatypes in Python 3 and I observed this.

import sys

val = None
print(sys.getsizeof(val))

The output was 16 as expected.

I tried making a list of 1000 locations of None and I expected the size to be 16*1000 = 16000 or more. But the result I got was different.

import sys

val = [None]*1000

print(sys.getsizeof(val))

The output was 8064. Nearly the half of the size I expected.

What is the reason for this.? Why memory allocated is less.?

3
  • 3
    sys.getsizeof returns only the size of the container (so, the container overhead and for the list the array of Py_Object pointers, on a 64-bit system, 8 bytes per pointer), not the objects inside the list. In this case, however, since None is a singleton, the total size is simply sys.getsizeof(val) + sys.getsizeof(None). In general, if a list references all unique objects, you have to get sys.getsizeof(my_list) + sum(map(sys.getsizeof, my_list)). Often, it is between these two extremes. Commented Jul 25, 2018 at 6:10
  • @juanpa.arrivillaga Great Explanation. Thanks Commented Jul 25, 2018 at 6:16
  • 1
    Note, from the docs: "Only the memory consumption directly attributed to the object is accounted for, not the memory consumption of objects it refers to." It also provides a link to a recursive sizeof recipe which will handle most complex objects (for example, caching based on identity). Commented Jul 25, 2018 at 6:18

2 Answers 2

6
import sys

val = None

print(sys.getsizeof(val))

Answer:

16

val = []

print(sys.getsizeof(val))

Answer: 

72

val = [None]

print(sys.getsizeof(val))

Answer:

80

so [None]*1000 = 1000* 8 + 72 = 8072

Note: No of bytes may vary depending on the environment

Sign up to request clarification or add additional context in comments.

2 Comments

On my system, sys.getsizeof([]) == 64, like in the OP. (Though I guess it varies.)
You're undercounting by 8 bytes here.
5

There is just a single None object referenced a thousand times. So the situation is this:

l[0]   ----> None
         /    ^
l[1]   -/     |
….            |
l[999]  -----/

And not this:

l[0]   ----> None

l[1]   ----> None
….
l[999] ----> None

This is more visible when repeating a mutable object, like this:

>>> l = [set()] * 3
>>> print(l)
[set(), set(), set()]
>>> l[0].add(1)
>>> print(l)
[{1}, {1}, {1}]

There is just a single, shared set object referenced three times, so changes to the set at l[0] also affect l[1] and l[2].

Python data structures such as list, set and dict are reference-based. In your case, most of the 8064 bytes you observed come from the object references (8 bytes per list element).

4 Comments

So what if I used a list and appended None to 1000 loations.?
Same result because there is only a single None object.
@SreeramTP None is a singleton, the same with True and False.
@juanpa.arrivillaga Got it. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.