I created two lists
l2, but each one with a different creation method:
import sys l1 = [None] * 10 l2 = [None for _ in range(10)] print('Size of l1 =', sys.getsizeof(l1)) print('Size of l2 =', sys.getsizeof(l2))
But the output surprised me:
Size of l1 = 144 Size of l2 = 192
The list created with a list comprehension is a bigger size in memory, but the two lists are identical in Python otherwise.
Why is that? Is this some CPython internal thing, or some other explanation?
When you write
[None] * 10, Python knows that it will need a list of exactly 10 objects, so it allocates exactly that.
When you use a list comprehension, Python doesn't know how much it will need. So it gradually grows the list as elements are added. For each reallocation it allocates more room than is immediately needed, so that it doesn't have to reallocate for each element. The resulting list is likely to be somewhat bigger than needed.
You can see this behavior when comparing lists created with similar sizes:
>>> sys.getsizeof([None]*15) 184 >>> sys.getsizeof([None]*16) 192 >>> sys.getsizeof([None for _ in range(15)]) 192 >>> sys.getsizeof([None for _ in range(16)]) 192 >>> sys.getsizeof([None for _ in range(17)]) 264
You can see that the first method allocates just what is needed, while the second one grows periodically. In this example, it allocates enough for 16 elements, and had to reallocate when reaching the 17th.