Глубокие копии взаимосвязанных объектов со ссылками друг на друга

У меня есть структура данных графа Overlay , которая состоит из экземпляров, которые связаны между собой ребрами. Экземпляры представлены набором Instance объектов, а ребра представлены набором объектов Edge . Для удобства каждый экземпляр отслеживает входы и исходящие ребра, указывая на соответствующие существующие объекты Edge . Аналогично, каждый ребро указывает на объект- Instance источника и объекта-объекта- Instance .

Например, наложение может состоять из экземпляра i1 который подключен к другому экземпляру i2 через ребро e1 . e1.source – это ссылка на i1 а e2.dest – ссылка на i2 . i1.edges_out содержит ссылку на e1 и т. д. В целом есть только 2 Instance объекта и 1 объект Edge .

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

Я использую new_overlay = copy.deepcopy(old_overlay) и переопределяет __deepcopy__ в Overlay , Instance и Edge следующим образом:

В Overlay :

 def __deepcopy__(self, memodict={}): new_overlay = Overlay(self.template, set(), set()) # new, empty overlay new_overlay.instances = copy.deepcopy(self.instances, memodict) new_overlay.edges = copy.deepcopy(self.edges, memodict) return new_overlay 

В Instance :

 def __deepcopy__(self, memodict={}): # new instance with same attributes new_instance = Instance(self.attributes) # edges_in, _out should contain references to the existing edges, not new objects new_instance.edges_in = copy.deepcopy(self.edges_in, memodict) new_instance.edges_out = copy.deepcopy(self.edges_out, memodict) return new_instance 

В Edge :

 def __deepcopy__(self, memodict={}): # new edge with same source and destination: these should be references to existing instances, not new objects new_edge = Edge(copy.deepcopy(self.source, memodict), copy.deepcopy(self.dest, memodict)) new_instance.attribute = self.attribute # no need to deep copy return new_edge 

Я надеялся, что copy.deepcopy позаботится обо всем, используя memodict , но это не сработает: при проверке id объекта с помощью отладчика PyCharm ссылки в скопированном оверлее иногда неверны. Вместо ссылок на существующие объекты, например, существующие экземпляры в качестве источника / назначения для ребра, создаются новые экземпляры экземпляра.

Как я могу выполнить глубокую копию Overlay при сохранении структуры ссылок? Оба ребра должны иметь ссылки на экземпляры (источник / место назначения), а экземпляры должны иметь ссылки на ребра (edge_in / edge_out).