Более быстрая глубокая копия в Python; большой список в 15 раз медленнее, чем копирование - PullRequest
0 голосов
/ 05 марта 2020

У меня есть скрипт для демонстрации:

#!/usr/bin/env python3

import time
import copy

def reset():
    a = [[{'1': [5, 2, 6, 7, 9], '2': 6, '3': 5}], [{'1': [5, 2, 6, 7, 9], '2': 6, '3': 5}]]
    b = []
    return a, b

a, b = reset()

start = time.time()
b = list(a)
end = time.time()
print("list(a) took:", end-start)
a[0][0]['1'] = [1, 2, 3, 4, 5]
print("b changed with a" if b == a else "b did not change with a")
a, b = reset()

start = time.time()
b = a[:]
end = time.time()
print("a[:] took:", end-start)
a[0][0]['1'] = [1, 2, 3, 4, 5]
print("b changed with a" if b == a else "b did not change with a")
a, b = reset()

start = time.time()
b = copy.copy(a)
end = time.time()
print("copy(a) took:", end-start)
a[0][0]['1'] = [1, 2, 3, 4, 5]
print("b changed with a" if b == a else "b did not change with a")
a, b = reset()

start = time.time()
b = copy.deepcopy(a)
end = time.time()
print("deepcopy(a) took:", end-start)
a[0][0]['1'] = [1, 2, 3, 4, 5]
print("b changed with a" if b == a else "b did not change with a")

И вывод:

list(a) took: 1.1920928955078125e-06
b changed with a
a[:] took: 7.152557373046875e-07
b changed with a
copy(a) took: 3.337860107421875e-06
b changed with a
deepcopy(a) took: 2.5510787963867188e-05
b did not change with a

Нет ли более быстрого способа глубокой копии? Я передаю список функции, которая затем видоизменяется. Я хочу сохранить копию списка, прежде чем он был изменен для сравнения двух, но deepcopy слишком медленный. Я имею в виду выполнение 1 с против 15 с.

Пример моих данных приведен ниже:

[[{'w': [0.5372377247650572, 1.9111341091016385, -3.2165806256024116, -1.7154987465370053, 1.0917999534858416], 'o': 0.0004326739879156587, 'd': 3.586499431857422e-05}],[{'w': [7.298542669399767, -3.9021024252822105], 'o': 0.019860841402923542, 'd': 0.00105997759946847}, {'w': [-2.8024625186056764, -0.34819658506990847], 'o': 0.4135257109795849, 'd': -0.0016469874583619935}, {'w': [-6.018257518762189, 0.3317488378886934], 'o': 0.5815513019444986, 'd': -1.1787471334339458e-05}]]

Ответы [ 2 ]

1 голос
/ 05 марта 2020

Если вы стремитесь только обнаружить изменения, вместо того, чтобы сделать копию, вы можете попытаться сохранить только ха sh структуры и проверить, отличается ли новый ха sh:

d = [[{'1': [5, 2, 6, 7, 9], '2': 6, '3': 5}], [{'1': [5, 2, 6, 7, 9], '2': 6, '3': 5}]]

def hashIt(d):
    if isinstance(d,list):
        return hash(tuple(hashIt(i) for i in d))
    if isinstance(d,dict):
        return hash(tuple(((k,hashIt(v))) for k,v in d.items()))
    return hash(d)


hashBefore = hashIt(d)

d[1][0]["1"][2]=11

print(hashBefore == hashIt(d)) # false

d[1][0]["1"][2]=6

print(hashBefore == hashIt(d)) # true
1 голос
/ 05 марта 2020

Насколько я знаю, нет более быстрого способа скопировать экземпляр объекта в python, если вы хотите рекурсивное копирование объектов на нескольких уровнях. Python copy.deepcopy() создает новый составной объект, а затем рекурсивно вставляет в него копии объектов, найденных в оригинале. Таким образом, в основном он копирует все, что находится в объекте класса на нескольких уровнях. Но copy.copy () можно рассматривать как copy.deepcopy() только для одного уровня учеников. Следовательно, ожидается, что deepcopy() будет работать более или менее хуже, чем copy(), поскольку накладные расходы всегда выше. Следующий фрагмент может помочь вам понять

import copy

def printer(objs):
    for obj in objs:
        for key, val in sorted(obj.items()):
            print(key+':',val,end=' ')
        print()

x = [{'a':[1,2,3], 'b':[4,5,6], 'c':[7,8,9]},
     {'d':[1,2,3], 'e':[4,5,6], 'f':[7,8,9]},
     {'g':[1,2,3], 'h':[4,5,6], 'i':[7,8,9]}]
y, z = copy.copy(x), copy.deepcopy(x)

x[0]['a'][1] = 0
x[1]['e'][1] = 0
x[2]['i'][1] = 0

printer(x)
print()
printer(y)
print()
printer(z)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...