2

Suppose I have a class:

import copy
class TestClass:
    def __init__(self, value):
        if isinstance(value, TestClass):
            self = value.deepcopy()
        else:
            self.data = value

    def deepcopy(self):
        return copy.deepcopy(self)

where I want to write the code such that if an instance of a class is initialized by another instance of the same class, it will make a deepcopy of the second class.

Now, if I try

In []: x = TestClass(3)
In []: x.data
Out[]: 3

But if I try

 In []: y = TestClass(x)
 Out[]: y.data
 ...
 AttributeError: 'TestClass' object has no attribute 'data'

Why didn't the deepcopy happen when the instance x was passed to y ?

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
uday
  • 6,453
  • 13
  • 56
  • 94
  • http://stackoverflow.com/questions/1216356/is-it-safe-to-replace-a-self-object-by-another-object-of-the-same-type-in-a-meth – Eric Levieil Apr 12 '15 at 13:57
  • 2
    so, essentially, I can't just assign self to another instance, but need to copy every attribute of the other instance to the current instance? – uday Apr 12 '15 at 14:07
  • Or you can make a function that is not a constructor but returns a TestClass object. – Eric Levieil Apr 12 '15 at 14:11
  • When you do `self = ...`, you are not replacing the current object with the copied object, but you are making the variable `self` refer the copied object. – thefourtheye Apr 12 '15 at 14:22
  • 1
    In Python you'd normally say `y = x.copy()` rather than `y = TestClass(x)`. – Kos Apr 12 '15 at 14:29

1 Answers1

8

A solution:

import copy
class TestClass:
    def __init__(self, value):
        if isinstance(value, TestClass):
            self.__dict__ = copy.deepcopy(value.__dict__)
        else:
            self.data = value

This makes your example working. You want to do a 'copy constructor', in Python objects have a __dict__ attribute containing all members so you can just copy the dictionary from the original object and assign it to the new object __dict__.

mguijarr
  • 7,641
  • 6
  • 45
  • 72
  • this making a copy though, its not referencing the original object. – Jamie Marshall Mar 20 '19 at 21:57
  • @JamieMarshall if it is to reference the original object, I would say a [proxy](https://stackoverflow.com/questions/46052736/python-proxy-class) is better, ie. an object that would transparently transfers to the original object. With some added members, maybe. – mguijarr Mar 20 '19 at 22:42