How to clone objects in Python?

6

In some languages, in addition to instantiating 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 original state. p>

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

  $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 date information, but I just cloned and modified it for the time I needed.

Of course, above was just an example, but there are still other cases where creating a new instance of an object could become complicated due to dependencies on 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, where I realized it) are objects. But when it comes to class instances, is there any way to clone objects like they do in PHP?

To stop creating an instance of a class in Python we do not need a new operator, as in PHP.

So how would you clone an Object in Python? Is there a specific operator for this?

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

What about Python? Is there a special method for modifying the behavior of the class in relation to creating a clone?

    
asked by anonymous 04.11.2016 / 11:33

1 answer

6

In Python, the most common way to do this is to use the copy module of the default library.

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

from copy import copy
dt2 = copy(dt)

(* see last session d answers about datetime specifically)

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

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

The copy and deepcopy break a gallon - but could be implemented in a generic way, using pure Python, with few rows. The interesting thing about Python is that objects are defined in order to allow introspection, and in general do not violate these rules. If you, for example, want to copy an instance of a generic object, and do not have copy.copy , could: (1) call the% method of the object class explicitly, (2) update the __new__ of the new instance to be equal to __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)

Output:

20 30

But the copy still covers several corner cases, being able to copy objects that have attributes that are not in __dict__ , and etc ... (Just to note - the normal mechanism for instantiating a class calls the method __dict__ and then the __new__ of a class. So when we create a class, we usually only customize __init__ - when calling only the When you copy the attributes, which are in __init__ , you have your "clone")

datetime : Note that the __new__ object of the library for Python is immutable, so you can not change its time. This is necessary so that datetimes can 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)
    
04.11.2016 / 13:14