0

When I have a object-structure like this:

from copy import deepcopy

class A:
    def __init__(self, b):
        self.b = b
    def __deepcopy__(self, memodict):
        return A(deepcopy(self.b, memodict))

class B:
    def __init__(self, a):
        self.a = a
    def __deepcopy__(self, memodict):
        return B(deepcopy(self.a, memodict))

test_a = A(None)
test_b = B(None)
test_a.b = test_b
test_b.a = test_a
copy_a = deepcopy(test_a)

And I try to make a deepcopy of a object I get a "maximum recursion depth exceeded" error. Which I understand why this happens but I don't know what the best approach would be to solve this?

Help much appreciated

  • To understand recursion, you must first understand recursion. Seriously though: your code is calling itself to the point at which the call stack has exceeded the allowed size (`sys.maxrecursionlimit`). You need a base case or breakout condition to prevent this from happening. – JacobIRR Jun 07 '20 at 21:51
  • You should post some example test to see where the recursion problem is. How are the objects referenced to eatch other? – nadapez Jun 07 '20 at 22:35
  • you should post tested and working examples in questions. – nadapez Jun 07 '20 at 23:34
  • @JacobIRR Yeah I understand that, it was just because examples online did it like this I figured the copy.deepcopy function would handle the base case. – Lucas van der Horst Jun 08 '20 at 08:05
  • @nadapez I'm sorry, edited it so it has a working example – Lucas van der Horst Jun 08 '20 at 08:15

1 Answers1

1

You should not override __deepcopy__, just let deepcopy function do its work. By the way I had to remove annotation :B because its a foreward reference and gives name error.

from copy import deepcopy

class A:
    def __init__(self, b):
        self.b = b

class B:
    def __init__(self, a):
        self.a = a


a = A(None)
b = B(None)
a.b = b
b.a = a

aa = deepcopy(a)

print (aa is a) # -> False
print(aa.b is b) # -> False
print(aa.b.a is aa) # -> True

But if you for any reason want to override the __deepcopy__ you should do it like this:

from copy import deepcopy


class A:
    def __init__(self, b):
        self.b = b

    def __deepcopy__(self, memodict):
        a = A(None)
        memodict[id(self)] = a
        a.b = deepcopy(self.b, memodict)
        return a


class B:
    def __init__(self, a: A):
        self.a = a

    def __deepcopy__(self, memodict):
        b = B(None)
        memodict[id(self)] = b
        b.a = deepcopy(self.a, memodict)
        return b


a = A(None)
b = B(None)
a.b = b
b.a = a

aa = deepcopy(a)
print(aa is a)  # -> False
print(aa.b is b)  # -> False
print(aa.b.a is aa)  # -> True

ref: https://stackoverflow.com/a/15774013/1951448

nadapez
  • 2,603
  • 2
  • 20
  • 26