2014-12-06 8 views
3

Мой ответ можно рассматривать как дополнение к this post.Функция Python между copy() и deepcopy()

У меня есть словарь, который содержит списки объектов. Мне нужна функция между функциями copy и deepcopy в модуле copy. Я хочу что-то, что выполняет глубокую копию встроенных структур и примитивов Python (целые числа, наборы, строки, списки и т. Д.), Но не создает глубокую копию пользовательских объектов (или не примитивных, неагрегатных объекты).

Возможно, мне понадобится изменить метод моих объектов __deepcopy__, но я не совсем уверен, как это сделать должным образом. Также предпочтительным является решение, которое не модифицирует метод __deepcopy__ объекта, в том случае, если я хочу сделать глубокую копию объекта в будущем скрипте.

Предположим, что это вершина моего файла Python:

import copy 

class Obj(): 
    def __init__(self,i): 
     self.i = i 
     pass 

d = {0:Obj(5),1:[Obj(6)],2:[]} 
d2 = copy.deepcopy(d) 

В качестве примера, я перечислю некоторые фрагменты кода ниже, наряду с фактическим выходом и желаемым выходом.

Сниппет 1

d[1][0].i=7 
print "d[1][0].i:",d[1][0].i,"d2[1][0].i:",d2[1][0].i 
  • Фактический выход: d[1][0].i: 7 d2[1][0].i: 6
  • Желаемая Выход d[1][0].i: 7 d2[1][0].i: 7

Сниппет 2

d[0].i = 6 
print "d[0].i:",d[0].i,"d2[0].i:",d2[0].i 
  • Фактический выход: d[0].i: 6 d2[0].i: 5
  • Желаемая Выход d[0].i: 6 d2[0].i: 6
+1

Я думаю, вам придется подставить '__deepcopy__' или сделать свой собственный метод – lolopop

+0

вы абсолютно _need_ копии?часто лучший способ решить такую ​​проблему - избегать копирования чего-либо в первую очередь. – Eevee

+0

@Eevee: Проблема в том, что я решаю итеративный вариант, где я просматриваю дерево возможных решений. Я наращиваю решение постепенно (рекурсия для меня слишком медленная). Корневое состояние - это словарь списков, и каждый список содержит объект, который я определил. Мне нужно изменить списки временных словарей, которые я определяю во время итерации, без изменения корня. Мне также нужно хранить ссылки на объекты вместо самих объектов (ради пространства и функциональности). – Matt

ответ

0

Вы можете увидеть, как (чистый питон) deepcopy и copy методы сделаны here. Вы можете попытаться сделать более простой для своих конкретных объектов или попытаться изменить «оригинал».

Вы также можете изменить __deepcopy__ метод ваших объектов, чтобы вернуться просто self, но это может повлиять на их поведение - если вы хотите deepcopy их позже, конечно, но если вы используете какие-то внешние библиотеки, например, отладчиков или графического интерфейса.

1

Здесь вы идете, прямо из документации:

import copy 

class Obj: 
    def __init__(self, i): 
     self.i = i 

    def __deepcopy__(self, memo): 
     return self 

Вашего последний пример не кажется правильным, так как d3 неглубокой копия d, поэтому список индексироваться 2 должен оставаться такой же ссылкой.

Чтобы обеспечить глубокое копирование в качестве опции, вы можете установить некоторый атрибут в объекте и проверить его на __deepcopy__.

+0

Хороший вызов на d3 и Snippet 3! Не уверен, что я думал, когда писал их :). Я просто удалил этот код. – Matt

Смежные вопросы