1

I am running a 64-bit machine. If i type getsizeof(int()), i get 24. What are the elements or objects that use these 24 bytes? Here are some more confusing results: getsizeof(0) returns 24. getsizeof(1) returns 28. Why does 1 take 4 more bytes than 0? And getsizeof(1.5) returns 24. Why does 1.5 which is a float takes smaller size than an integer 1.

0x5961736972
  • 148
  • 1
  • 7
  • Try playing with `math.factorial` :) For example getsizeof(math.factorial(13000)) -> 21216 :D – minder Aug 19 '20 at 08:50
  • 2
    See [Python internals: Arbitrary-precision integer implementation](https://rushter.com/blog/python-integer-implementation/#:~:text=Generally%2C%20In%20languages%20like%20C,are%20represented%20as%20a%20bignum) or for an [SO Answer](https://stackoverflow.com/questions/10365624/sys-getsizeofint-returns-an-unreasonably-large-value) – DarrylG Aug 19 '20 at 08:56

1 Answers1

5

I'll talk just about ints for now, and look at floats at the end.

In Python, unlike C and many other languages, int is not just a datatype storing a number. It is a full object, with extra information about the object (more detail here).

This extra information takes up lots of space, which is why the objects can seem unusually large. Specifically, it takes up 3 lots of 8 bytes (3*8=24 bytes). These are a reference count, a type and a size.

Python stores integers using a specific number of bytes depending on how large they are. Specifically:

0 <= n < 2**0:
    requires 24 bytes
2**0 <= n < 2**30:
    requires 28 bytes
2**30 <= n < 2**60:
    requires 32 bytes

In general, for every increase of 30 powers of 2 (for want of better terminology!), 4 extra bytes are required.

This pattern also follows for the negative numbers, just going the opposite direction.

These specific values are the values on my computer, but will vary depending on the environment you're running Python on. However, the general patterns are likely to be the same.

I believe (as explained a little here) that the reason zero alone uses less space is that the only int which can be represented using just 24 bytes is zero, so there is no need to additionally store the actual value, reducing the size. It's possible I've misunderstood this specific case so please correct me below if so!

However, floats are stored differently. Their values are simply stored using 64 bits (i.e. a double), which means there are 8 bytes representing the value. Since this never varies, there is no need to store the size as we do with integers, meaning there are only two 8 byte values to store alongside the specific float value. This means the total size is two lots of 8 bytes for the object data and one lot of 8 bytes for the actual value, or 24 bytes in total.

It is this property of not needing to store the value's size that frees up 8 bytes, which means 1.5 requires less space than 1.

Reece Coombes
  • 394
  • 2
  • 9
  • 2
    As for 0 needing "no" space: CPython integers are roughly numbers in base 4294967296 - or unsigned 4-byte "digits". That means ``2**32`` is a "2-digit" number, just like ``12`` in base-10. Likewise, ``1`` is a "1-digit" number, just like ``1`` in base-10. We could of course write ``01``, or ``001``, or so on, in any base, but there is no advantage so *leading zeroes are dropped* to just ``1``. Likewise, the "number" ``0`` can be expressed without leading zeroes – giving a "0-digit" number. The only space required is to mark the object as an integer, which clearly defines a 0-digit number then. – MisterMiyagi Aug 19 '20 at 12:35