Допустим, у меня есть 2 словаря на Python, например:
d1 = {}
d2 = {}
d1[(i, j)] = 10
d2[(i, j)] = 20
Вместо этого я мог бы сделать это так:
d = {}
d[(i, j)] = (10, 20)
Доступ к нему можно было сделать с помощью d[(i,j)][0]
и d[(i,j)][1]
.
Я хотел бы спросить вот о чем:
Требуется ли второму варианту меньше памяти, чем первому?
Если да, то это половина памяти?
Мне нужно использовать очень большие словари в программе, которую я пишу, и если второе решение лучше, я бы выбрал его.
Я предлагаю сделать некоторые дальнейшее чтение для словарей в учебнике по Python (подглава 5.5). Затем вы можете лучше указать, что вы хотите сделать. Совсем другое дело, если у вас два отдельных словаря или только один.
Вам также следует обратить внимание на более специализированные структуры данных, такие как массивы numpy
, которые оптимизированы для данных в матричном стиле.
Протестировано на машине с Windows 10 в 32-битной версии Python 3.7.3:
Это заняло 155 МБ памяти:
>>> d1 = {(i, j): 10 for i in range(1000) for j in range(1000)}
>>> d2 = {(i, j): 20 for i in range(1000) for j in range(1000)}
А это всего 79МБ:
>>> d = {(i, j): (10, 20) for i in range(1000) for j in range(1000)}
Таким образом, второй, очевидно, лучше с точки зрения использования памяти, но это совершенно разные решения, и трудно сказать, какое из них «лучше» в целом. Все зависит от варианта использования.
Редактировать:
Разница намного меньше, но все же значительна при использовании случайных значений (с уникальными id
s).
Это заняло 157 МБ:
>>> from random import randint
>>> d1 = {(i, j): randint(0, 100) for i in range(1000) for j in range(1000)}
>>> d2 = {(i, j): randint(0, 100) for i in range(1000) for j in range(1000)}
А это 119 МБ:
>>> from random import randint
>>> d = {(i, j): (randint(0, 100), randint(0, 100)) for i in range(1000) for j in range(1000)}
Это удивительно. Разве кортеж из 2 элементов не занимает больше памяти, чем сами 2 элемента?
@Barmar Я предполагаю, что да, но дополнительный словарь, очевидно, имеет много накладных расходов.
Также удивительно, я ожидаю, что это будет асимптотически незначительным. Возможно, в хэш-таблице есть много дополнительного места, чтобы избежать коллизий.
Является ли второй кортеж 1000 * 1000 или один кортеж и 1000 * 1000 ссылок на один и тот же кортеж?
@JamesKPolk Это одно и то же id
в каждом из них.
@JamesKPolk >>> id(d[(2,3)]) 17966064
, >>> id(d[(999,500)]) 17966064
.
Я не думаю, что OP предполагал, что каждая запись в словаре будет одинаковой.
Каждая запись не будет отличаться. Применяется ли это в данном случае?
что если поставить (i,j) вместо (10,20)?
>>> a = [(10, 20) for i in (0, 1)] >>> a[0] is a[1] True
@ruohola Спасибо!! Всего одна маленькая деталь. Если у нас есть 4 элемента (i,j,k,l) вместо 2, не могли бы вы проверить, сколько памяти ему нужно?
@pikpapo: Вы можете сами проверить использование памяти. Если вы не знаете, как это сделать, задайте отдельный вопрос на StackOverflow.
@pikpapo Трудно сравнивать, так как вы не можете разделить 1000000 на 4 цикла равномерно. Вы можете легко проверить использование памяти определенными словарями с помощью диспетчера задач :)
Итак, мы можем предположить, что чем больше одинаковых элементов, тем меньше памяти требуется словарю?
@Epitheoritis Да, очевидно. Для случайных примеров потребуется создать миллион объектов с уникальными id
, что, естественно, требует много памяти.
Is it half of the memory?
- Да.