Ben Usman Ben Usman - 3 months ago 27
Python Question

__deepcopy__ object with cyclic references

from copy import deepcopy

class DoubleLinkedListNeedsDeepCopy:
def __init__(self, val, tail=None):
self.val = val
self._next_node = None
self._tail = tail or self

def append(self, new_val):
next_node = type(self)(new_val, self._tail)
self._next_node = next_node
return next_node

def __deepcopy__(self, memo):
new_copy = type(self)(self.val)
new_copy._next_node = deepcopy(self._next_node, memo)
new_copy._tail = deepcopy(self._tail, memo)
return new_copy

def next(self):
return self._next_node

def tail(self):
return self._tail

def is_last(self):
return self._next_node == None

linked_list = head = DoubleLinkedListNeedsDeepCopy(1)
for i in range(2, 5):
head = head.append(i)

def print_list(linked_list):
cur = linked_list
for i in range(20):
print(cur.val, end=' ')

if cur.is_last:
cur =

import sys

print_list(linked_list) = 5
list_copy = deepcopy(linked_list) = 8

Expected output is:

1 2 3 4
1 2 5 4
1 2 8 4
1 2 5 4

However it fails with
after following a recursive path:

(that is of course a toy example, I need a complicated tree-like structure to be copied in real-life scenario)


It turned out that in most cases (if you don't need to explicitly exclude certain fields from your copy), you can just do deepcopy(obj) even if obj has self-links or other else nasty properties.