Могу ли я использовать меньше памяти для сохранения однозначного числа?

#python #python-3.x #memory

#python #python-3.x #память

Вопрос:

Я знаю, что Python — не лучший язык управления памятью, но есть ли способ хранить небольшие числа в меньшую часть памяти, чем целое число?

В настоящее время я работаю над программой на Python с поиском по ширине и использую один параметр в классе, который может иметь значение только от 0 до 9. Я хочу сохранить это как можно более эффективно, потому что — хорошо, если у меня размер 1B или 3B имеет значение, когда вам нужно просмотреть несколько тысяч переменных в оперативной памяти.

Комментарии:

1. При нескольких тысячах объектов вы все равно будете находиться в диапазоне КБ. Если вы не работаете на какой-то платформе с очень ограниченными ресурсами, это не будет иметь большого значения

2. Это встроенная система? В большинстве случаев обычное целое число достаточно мало, чтобы о нем не беспокоиться.

3. В CPython кэшируются небольшие целые числа. Итак, есть только служебные данные указателя, 8 байт. Однако, если вы хотите сохранить много маленьких целых чисел, вы можете использовать array.array или даже numpy

Ответ №1:

не уверен, что это действительно того стоит, но вы всегда можете закодировать целые числа в [0, 1, ..., 9] 4 бита и сохранить несколько из них в python int . их упаковка и распаковка — это затем некоторый сдвиг и маскировка:

 SHIFT = 4
MASK = 0xf

integers = [0, 1, 5, 3]

# pack list into int
store = 0
for i in integers:
    store <<= SHIFT
    store ^= i

# unpack list from int
unpacked = []
for _ in range(len(integers)):
    unpacked.append(store amp; MASK)
    store >>= SHIFT
unpacked.reverse()

assert integers == unpacked
  

struct модуль также может быть полезен.

Ответ №2:

С собственным кодом python вы не можете, поскольку python int жестко запрограммирован на 24 байта для поддержки длинного целого числа. Что эффективно, поскольку в вашем случае параметр функции принимает однозначное число

Но если вы помните, что C имеет решение, unsigned char в C занимает 1 байт и имеет диапазон чисел от 0 - 255

Итак, в python это будет выглядеть так

 >>> from ctypes import c_ubyte
>>> ten = c_ubyte(10)
>>> ten
c_ubyte(10)
>>> type(ten)
<class 'ctypes.c_ubyte'>
>>> ten.value
10
>>> type(ten.value)
<class 'int'>
>>> 
  

Комментарии:

1. У ctypes оболочек нет накладных расходов на память?

2. В моей системе это ctypes.c_ubyte значение имеет гораздо больше накладных расходов, чем простое int . Это было бы полезно только для экономии памяти, если бы вы использовали довольно большой массив ubytes, так что для всех значений существует только один экземпляр накладных расходов.