"sys.getsizeof(int)" возвращает неоправданно большое значение?
Я хочу проверить размер типа данных int в Python:
import sys
sys.getsizeof(int)
Получается "436", что не имеет смысла для меня. В любом случае, я хочу знать, сколько байтов (2,4,..?) Int займет на моей машине.
1 ответ
Краткий ответ
Вы получаете размер класса, а не экземпляра класса. Вызов int
чтобы получить размер экземпляра:
>>> sys.getsizeof(int())
24
Если этот размер все еще кажется немного большим, помните, что Python int
сильно отличается от int
в (например) в. В Python int
является полноценным объектом. Это означает, что есть дополнительные накладные расходы.
Каждый объект Python содержит по крайней мере refcount и ссылку на тип объекта в дополнение к другому хранилищу; на 64-битной машине это занимает 16 байтов! int
внутренние компоненты (как определено стандартной реализацией CPython) также со временем менялись, так что объем занимаемой дополнительной памяти зависит от вашей версии.
Некоторые подробности о int
объекты в Python 2 и 3
Вот ситуация в Python 2. (Часть этого взята из сообщения в блоге Лорана Люса). Целочисленные объекты представлены в виде блоков памяти со следующей структурой:
typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject;
PyObject_HEAD
это макрос, определяющий хранилище для refcount и типа объекта. Это подробно описано в документации, и код можно увидеть в этом ответе.
Память выделяется большими блоками, поэтому для каждого нового целого числа нет узкого места. Структура для блока выглядит следующим образом:
struct _intblock {
struct _intblock *next;
PyIntObject objects[N_INTOBJECTS];
};
typedef struct _intblock PyIntBlock;
Сначала все они пусты. Затем каждый раз, когда создается новое целое число, Python использует память, на которую указывает next
и приращения next
указать на следующий свободный целочисленный объект в блоке.
Я не совсем уверен, как это изменится, когда вы превысите емкость обычного целого числа, но как только вы это сделаете, размер int
становится больше. На моей машине, в Python 2:
>>> sys.getsizeof(0)
24
>>> sys.getsizeof(1)
24
>>> sys.getsizeof(2 ** 62)
24
>>> sys.getsizeof(2 ** 63)
36
В Python 3, я думаю, общая картина та же, но размер целых чисел увеличивается более постепенно:
>>> sys.getsizeof(0)
24
>>> sys.getsizeof(1)
28
>>> sys.getsizeof(2 ** 30 - 1)
28
>>> sys.getsizeof(2 ** 30)
32
>>> sys.getsizeof(2 ** 60 - 1)
32
>>> sys.getsizeof(2 ** 60)
36
Эти результаты, конечно, все зависит от оборудования! YMMV.
Изменчивость в целочисленном размере в Python 3 является намеком на то, что они могут вести себя больше как типы переменной длины (например, списки). И действительно, это оказывается правдой. Вот определение Cstruct
за int
объекты в Python 3:
struct _longobject {
PyObject_VAR_HEAD
digit ob_digit[1];
};
Комментарии, сопровождающие это определение, обобщают представление целых чисел в Python 3. Ноль представлен не сохраненным значением, а объектом с нулевым размером (вот почему sys.getsizeof(0)
является 24
байт в то время как sys.getsizeof(1)
является 28
). Отрицательные числа представлены объектами с отрицательным атрибутом размера! Так странно.