Краткий ответ: накладные расходы объекта Python убивают вас. В Python 2.x на 64-битной машине список строк потребляет 48 байтов на элемент списка даже до учета содержимого строк. Это превышает 8,7 Гб на размер массива, который вы описываете.
На 32-битной машине это будет немного лучше: только 28 байтов на запись списка.
Более длинное объяснение: вы должны знать, что сами объекты Python могут быть довольно большими: даже простые объекты, такие как int, float и string. В вашем коде вы получаете список списков строк. На моей (64-битной) машине даже пустой строковый объект занимает 40 байтов, и к этому вам нужно добавить 8 байтов для указателя списка, который указывает на этот строковый объект в памяти. Так что это уже 48 байтов на запись, или около 8,7 Гб. Учитывая, что Python выделяет память в количестве, кратном 8 байтам за раз, и что ваши строки почти наверняка непусты, вы фактически просматриваете 56 или 64 байта (я не знаю, какова длина ваших строк) для каждой записи.
Возможные решения:
(1) Вы могли бы (немного) сделать лучше, преобразовав свои записи из строк в целые или плавающие в зависимости от ситуации.
(2) Вы бы сделали намного лучше, используя тип Python array (не совпадающий со списком!) Или numpy : затем Ваши целые числа или числа с плавающей запятой будут занимать всего 4 или 8 байт каждый.
Начиная с Python 2.6, вы можете получить основную информацию о размерах объектов с помощью функции sys.getsizeof
. Обратите внимание, что если вы примените его к списку (или другому контейнеру), тогда возвращаемый размер не будет включать размер содержащихся объектов списка; только структура, используемая для хранения этих объектов. Вот некоторые значения на моей машине.
>>> import sys
>>> sys.getsizeof("")
40
>>> sys.getsizeof(5.0)
24
>>> sys.getsizeof(5)
24
>>> sys.getsizeof([])
72
>>> sys.getsizeof(range(10)) # 72 + 8 bytes for each pointer
152