Быстрый способ скопировать словарь в Python

У меня есть программа Python, которая много работает со словарями. Я должен делать копии словарей тысячи раз. Мне нужна копия обоих ключей и связанного содержимого. Копия будет отредактирована и не должна быть привязана к оригиналу (например, изменения в копии не должны влиять на оригинал.)

Ключи - это строки, значения - это целые числа (0/1).

В настоящее время я использую простой способ:

newDict = oldDict.copy()

Профилирование моего кода показывает, что операция копирования занимает большую часть времени.

Существуют ли более быстрые альтернативы методу dict.copy()? Что было бы быстрее?

Ответ 1

Глядя на источник C для операций Python dict, вы можете увидеть, что они делают довольно наивную (но эффективную) копию. Это по существу сводится к вызову PyDict_Merge:

PyDict_Merge(PyObject *a, PyObject *b, int override)

Это позволяет быстро проверять такие вещи, как если они являются одним и тем же объектом и если в них есть объекты. После этого он делает щедрое одноразовое изменение размера/выделение целевому dict, а затем копирует элементы один за другим. Я не вижу, чтобы вы становились намного быстрее, чем встроенный copy().

Ответ 2

По-видимому, dict.copy быстрее, как вы говорите.

[[email protected] ~]$ python -m timeit -s "d={1:1, 2:2, 3:3}" "new = d.copy()"
1000000 loops, best of 3: 0.238 usec per loop
[[email protected] ~]$ python -m timeit -s "d={1:1, 2:2, 3:3}" "new = dict(d)"
1000000 loops, best of 3: 0.621 usec per loop
[[email protected] ~]$ python -m timeit -s "from copy import copy; d={1:1, 2:2, 3:3}" "new = copy(d)"
1000000 loops, best of 3: 1.58 usec per loop

Ответ 3

Можете ли вы предоставить образец кода, чтобы я мог видеть, как вы используете copy() и в каком контексте?

Вы можете использовать

new = dict(old)

Но я не думаю, что это будет быстрее.

Ответ 4

В зависимости от того, что вы оставляете до спекуляции, вы можете захотеть обернуть оригинальный словарь и сделать вид копирования на запись.

"Копировать" - это словарь, который ищет материал в "родительском" словаре, если он еще не содержит ключ, но сам по себе внесет изменения.

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

Ответ 5

Однако измерения зависят от размера словаря. Для 10000 записей копия (d) и d.copy() почти одинаковы.

a = {b: b for b in range(10000)} 
In [5]: %timeit copy(a)
10000 loops, best of 3: 186 µs per loop
In [6]: %timeit deepcopy(a)
100 loops, best of 3: 14.1 ms per loop
In [7]: %timeit a.copy()
1000 loops, best of 3: 180 µs per loop