"sys.getsizeof(int)" возвращает неоправданно большую ценность? - программирование
Подтвердить что ты не робот

"sys.getsizeof(int)" возвращает неоправданно большую ценность?

Я хочу проверить размер типа данных int в python:

import sys
sys.getsizeof(int)

Это выходит за "436", что для меня не имеет смысла. Во всяком случае, я хочу знать, сколько байтов (2,4,...?) Int будет использоваться на моей машине.

4b9b3361

Ответ 1

Короткий ответ

Вы получаете размер класса, а не экземпляр класса. Вызовите int, чтобы получить размер экземпляра:

>>> sys.getsizeof(int())
24

Если этот размер по-прежнему кажется немного большим, помните, что Python int сильно отличается от int в (например) c. В Python объект int является полнофункциональным. Это означает дополнительные накладные расходы.

Каждый объект Python содержит по крайней мере refcount и ссылку на тип объекта в дополнение к другому хранилищу; на 64-битной машине, которая занимает 16 байтов! Внутренние элементы int (как определено стандартной реализацией CPython) также со временем изменились, поэтому количество дополнительного хранилища зависит от вашей версии.

Некоторые сведения о объектах int в Python 2 и 3

Здесь ситуация в Python 2. (Некоторые из них адаптированы из сообщения в блоге Laurent Luce). Целочисленные объекты представляются в виде блоков памяти со следующей структурой:

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 - это намек на то, что они могут вести себя как типы переменной длины (например, списки). И действительно, это оказывается правдой. Здесь определение C struct для объектов int в Python 3:

struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};

комментарии, которые сопровождают это определение, суммируют представление Python 3 целых чисел. Ноль представлен не хранимым значением, а объектом с нулевым размером (поэтому sys.getsizeof(0) - это 24 байты, а sys.getsizeof(1) - 28). Отрицательные числа представлены объектами с атрибутом отрицательного размера! Настолько странно.