2014-12-08 3 views
2

Я пытаюсь создать объект с кучей словарей (пример ниже):Override DeepCopy с копией

class test(object): 
    def __init__(self): 
     self.test_dict1 = {} 
     self.test_dict2 = {} 
     ... 

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

a = test() 
for i in range(1000): 
    b = copy.deepcopy(a) 

    # do stuff to b and output result 
    ... 

Однако большая часть содержимого словаря останется неизменной. Я мог бы просто использовать copy.deepcopy(), но это очень медленно, потому что он должен сделать копию ВСЕГО словарного контента (он очень большой), и b не будет очень отличаться a, поэтому имеет смысл ссылаться на a для самых часть и только переопределить ключи для элементов, которые были изменены в b.

Поскольку словари не содержат каких-либо изменяемых элементов (т. Е. Все целые числа или строки), использование copy.copy() в каждом отдельном словаре должно работать и будет значительно быстрее. Однако, поскольку a является объектом класса, этот код будет также изменить a:

# This code will modify a whenever b is modified 
a = test() 
for i in range(1000): 
    b = copy.copy(a) 

    # do stuff 
    ... 

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

+0

Я предполагаю, что я должен добавить, что я читал пост [здесь] (http://stackoverflow.com/questions/1500718/what-is-the-right-way-to-override-the-copy-deepcopy-operations-on-an-object-in-p), но я не знаю, я действительно понимаю, как заставить его делать то, что я хочу. Я думал использовать что-то вроде «return test (copy.copy (dict1), copy.copy (dict2))» и модификации конструктора для 'test()' для включения аргументов, но это не сработало. – ecksc

+0

Я думаю, что я мог бы сделать что-то похожее на приведенное выше и использовать 'b = test (copy.copy (a.test_dict1), copy.copy (a.test_dict2), ...)', но этот синтаксис кажется довольно громоздким. – ecksc

+1

Я бы использовал другой подход, который использует '' collections.ChainMap''. Таким образом, вы можете запросить каждый желаемый сценарий. – randomusername

ответ

0

Поскольку никто другой не рискнул решить это, я опубликую свое собственное решение. Я в конечном итоге изменения конструктора для test класса так, чтобы он мог принимать в качестве аргументов, а затем передавая мелкие копии словарей, например, так:

import copy 

class test(object): 
    def __init__(self, test_dict1 = {}, test_dict2 = {}): 
     self.test_dict1 = test_dict1 
     self.test_dict2 = test_dict2 
    ... 

a = test() 

# Set up initial values for a 
... 

for i in range(1000): 
    b = test(copy.copy(a.test_dict1), copy.copy(a.test_dict2) 

    # do stuff 
    ... 
Смежные вопросы