How to clone objects in Python?

Asked

Viewed 2,127 times

6

In some languages, besides being able to instantiate a class to construct a given object, we can also clone an existing instance, if we want an object with the same characteristics of the current instance, but without changing the state of the original.

For example, if I wanted to modify a copy of an object DateTime in PHP, to use the same information as the date of the object of that instance, but having an instance only with the modified time, I could do so:

  $date = new Date('2015-01-01 00:00:00');

  $date2 = clone $date;

  // não precisei redefinir a data, mas só a hora

  $date2->setTime(23, 59, 59); 

Above, it was not necessary to create a new instance with the date information, but I just cloned and modified it to the time I needed.

Of course, the above was just an example, but there are still other cases where the creation of a new instance of an object could become complicated, due to dependencies of an object. Then we can clone to have the same information in a new object, but without modifying the original.

In Python I also realize that everything (or almost everything up, as I noticed) are objects. However, when it comes to class instances, there is some way to clone objects like in PHP?

To stop creating an instance of a Python class we don’t need an operator new, as in PHP.

So what would be the way to clone an Object in Python? There is a specific operator for this?

Another thing is that in PHP we can use a magic method within the class called __clone to determine the behaviour of that class when a clone is created.

What about in Python? Is there a special method to modify the behavior of the class in relation to the creation of a clone?

  • Wallace will be looking for something like https://docs.python.org/3.5/library/copy.html, http://www.python-course.eu/deep_copy.php?

  • Like this. Interesting to know that Python solved this with a module...

1 answer

6


In Python, the most common way to do this is by using the module copy of the standard library.

If dt is a datetime, you can create a copy by making:

from copy import copy
dt2 = copy(dt)

(* see last session d replies about the datetime specifically)

The module tamem has the method deepcopy, and the big difference is that while the copy will only copy the instance - and keep internal references to objects that are pointed by attributes.

In particular for data structures with several nested lists and dictionaries - the deepcopy will make a recursive copy of each list and dictionary in its structure - while the copy will create a copy of only the object passed, but keep all internal references.

The copy and deepcopy break a gallon - but could be implemented in a generic form, using pure Python, with few lines. The interesting thing about Python language is that objects are defined in a way that allows introspection, and in general do not violate these rules. Therefore, if you, for example, wanted to copy an instance of a generic object, and did not have the copy.copy could: (1) call the method __new__ object class explicitly, (2) update attribute __dict__ of the new instance to be equal to the __dict__ of the copied object:

obj = MinhaClasse()
obj.a = 20
obj.b = 30

obj2 = type(obj).__new__(type(obj))
obj2.__dict__.update(obj.__dict__)
print (obj2.a, obj2.b)

Exit:

20 30

But the copy still covers several corner cases, being able to copy objects that have attributes that are not in the __dict__, and so on... (Just for the record - the normal mechanism for instantiating a class calls the method __new__ and soon after the __init__ of a class. So when we create a class, we usually just customize the __init__ - by calling only the __new__, the new object is not initialized with any value. When copying the attributes, which are in the __dict__, you have your "clone")

datetime: Note that the object datetime Python’s Bible library is immutable, so you can’t change its time. This is necessary for datetimes to be used as dictionary keys. If you need to create another datetime, keeping the date and changing the time as in your example, you need to do an auxiliary function that does this 'manually':

def changetime(dt, new_time):
    return  datetime.datetime(dt.year, dt.month, dt.day, new_time.hour, new_time.minute, new_time.second)
  • Thank you so much for the answer. Datetime didn’t worry me much, because it was the first example that came to mind when I quoted about PHP. The answer is very explanatory, I will mark it as useful :p

Browser other questions tagged

You are not signed in. Login or sign up in order to post.