0

I saw similar question here on stackoverflow but it wasn't satisfactorily answered. (link to this question - How to copy a python class? )

So my question is, is there any possible way to create a copy of class (instance of a class), that is stored in variable A and assign this copy of class to new variable B without having these variables A and B mutually dependent?

To be clear - is there a quite simple way?

Model situation would be:

class B:
    def __init__(self, li):
        self.l = li * 5
        self.u = 5       

class A:
    def __init__(self):
        self.x = [1, 2, 3]
        self.c = B([45, 1, 3])
    self.i = 1

x = A()
y = x #This copies only reference to x
Community
  • 1
  • 1
Jendas
  • 3,359
  • 3
  • 27
  • 55

3 Answers3

4

Implement __copy__() for your class, then you can use copy.copy() to create a copy of the instance. This can't be done automatically due to the nature of Python objects (there is no way of knowing what variables will be set on an instance, and no way of knowing how it's been mutated, it's up to you to ensure that data is copied correctly).

Normally, presuming a class that functions in a normal way, __copy__() will probably be something simple like this for a supposed class SomeClass:

def __copy__(self):
    return SomeClass(self.somefield, self.otherfield, self.somethingelse)

Naturally, exact implementation will vary wildly based on the class itself.

Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • I thought so. But I'm not sure if I really understand why this can not be done automatically. Can't I walk through the class recursively and every time I hit a mutable copy its elements to whole new mutable and continue like this? – Jendas Jan 18 '13 at 15:40
  • @Jendas Well, you could perform copies of everything in the object's `__dict__` or something hacky like that, but it's possible there is data in there that it doesn't make sense to copy over. Given we can monkey patch anything into a Python class, copying like this could produce unexpected results. When we copy we expect something with a new identity, but the same values - in some cases, the data in the object could be about identity, and copying it across would be wrong - Python can't automate stuff like that. – Gareth Latty Jan 18 '13 at 15:44
  • 1
    Another example, say the constructor does something outside of the class - this won't happen when we copy and object in this way, as the constructor won't get run (if it did, we would then introduce a requirement for an empty constructor to work, and do the right thing, and it quickly becomes more complex than doing it manually). – Gareth Latty Jan 18 '13 at 15:47
  • 1
    Another issue is that some of the attributes of the object could be properties, and if you access them through the instance they will lose their property-ness, which would be bad. The easiest way to deal with this is to have the instance know how to copy itself. – kindall Jan 18 '13 at 15:59
  • @kindall Exactly - Python being the language it is, there are probably tons of little edge cases like this that make it, at the very least, impractical to automate the task. – Gareth Latty Jan 18 '13 at 16:00
  • I see.... Well in that case, I will accept your answer. But, I am only curious, potentially, you admit, that it would be possible to do it automatically even though it is very impractical and hard to do? – Jendas Jan 18 '13 at 16:08
  • @Jendas More that, while it's possible to do, it would only work for basic classes, and could fail if certain things are added to the class or happen to the instance, or if the instances are used in more unusual ways. It would be a very *fragile* solution at best. If you want to try it, go ahead. You can get the data using [`vars(instance)`](http://docs.python.org/2/library/functions.html#vars), and push it into a new instance of the class. – Gareth Latty Jan 18 '13 at 16:11
1

If you want to create a separate copy of an object, try the copy module.

Kylotan
  • 18,290
  • 7
  • 46
  • 74
0

Using deepcopy in copy module is simpler. Erm, guys here's solution to those subtle problems: http://docs.python.org/2/library/copy.html#copy.deepcopy

LetMeSOThat4U
  • 6,470
  • 10
  • 53
  • 93
  • -1, Read further down that page, just like `copy()` needs `__copy__()`, `deepcopy()` requires you to implement `__deepcopy__()` on a class. – Gareth Latty Jan 18 '13 at 16:32