How to Create a Copy of an Object in Python

How can I create a copy of an object in Python?

To get a fully independent copy of an object you can use the copy.deepcopy() function.

For more details about shallow and deep copying please refer to the other answers to this question and the nice explanation in this answer to a related question.

Make copy of object instance in Python

If you want to make a copy then one way is using deepcopy:

from copy import deepcopy
B = deepcopy(A)

All = does is to assign another reference to the same object in memory. The deepcopy creates a whole new object in memory with the values of A and B will reference it. if you do the following you will see different prints:

B = A
print( id(A), id(B)) # Same ids

B = deepcopy(A)
print( id(A), id(B) # Different ids

Cloning an object in Python

The line self = sample only overwrites a local variable, it does not replace the object initially stored in self.

To copy instances of a class, you have to fully define how to build a new object from an existing one.

You do this by defining the __copy__ and __deepcopy__ methods. These are the dunder methods used by copy.copy and copy.deepcopy respectively.

Although, note that it is bad practice to have input in your __init__ as it impedes the above solution. You should separate your logic and your IO.

import copy

class test():
def __init__(self, a, b):
self.a, self.b = a, b

def __copy__(self):
return type(self)(self.a, self.b)

# Here we encapsulate the IO part of your code
def test_factory():
a = int(input())
b = int(input())
return test(a, b)

foo = test_factory()
... # input the attributes
bar = copy.copy(foo) # a copy of your object

How to copy a Python class instance if deepcopy() does not work?

I have mostly figured it out. The only problem which I cannot overcome is knowing an acceptable set of initialization arguments (arguments for __init__) for all classes. So I have to make the following two assumtions:

1) I have a set of default arguments for class C which I call argsC.
2) All objects in C can be initialized with empty arguments.

In which case I can
First:
Initialize a new instance of the class C from it's instance which I want to copy c:

c_copy = c.__class__(**argsC)

Second:
Go through all the attributes of c and set the attributes c_copy to be a copy of the attributes of c

for att in c.__dict__:
setattr(c_copy, att, object_copy(getattr(c,att)))

where object_copy is a recursive application of the function we are building.

Last:
Delete all attributes in c_copy but not in c:

for att in c_copy.__dict__:
if not hasattr(c, att):
delattr(c_copy, att)

Putting this all together we have:

import copy

def object_copy(instance, init_args=None):
if init_args:
new_obj = instance.__class__(**init_args)
else:
new_obj = instance.__class__()
if hasattr(instance, '__dict__'):
for k in instance.__dict__ :
try:
attr_copy = copy.deepcopy(getattr(instance, k))
except Exception as e:
attr_copy = object_copy(getattr(instance, k))
setattr(new_obj, k, attr_copy)

new_attrs = list(new_obj.__dict__.keys())
for k in new_attrs:
if not hasattr(instance, k):
delattr(new_obj, k)
return new_obj
else:
return instance

So putting it all together we have:

argsC = {'a':1, 'b':1}
c = C(4,5,r=[[1],2,3])
c.a = 11
del c.b
c_copy = object_copy(c, argsC)
c.__dict__

{'a': 11, 'r': [[1], 2, 3]}

c_copy.__dict__

{'a': 11, 'r': [[1], 2, 3]}

c.__dict__

{'a': 11, 'r': [[1, 33], 2, 3]}

c_copy.__dict__

{'a': 11, 'r': [[1], 2, 3]}

Which is the desired outcome. It uses deepcopy if it can, but for the cases where it would raise an exception, it can do without.

How to copy instances of a custom defined class in Python 3.3?

In general, you can use the copy module to produce copies of Python objects.

  • copy.copy() will produce a shallow copy; a new instance is created but all attributes are simply copied over. If any of your attributes are mutable and you mutate those objects you'll see those changes reflected on both objects.

  • copy.deepcopy() will produce a copy recursively; any mutable objects will themselves be cloned.

If your class implements a __copy__ method it'll be used to create a shallow copy of the object; return a new instance with attributes copied over and altered as needed.

Similarly, you can implement a __deepcopy__ method to implement a custom deep copy method; it'll be passed the memo state, pass this on to recursive copy.deepcopy() calls.

Note that you cannot use this to copy a class object however. Classes are meant to be singletons; you don't need to create a copy in that case. You can use subclassing instead, or a class factory function, to produce distinct class objects.

how to make a copy of a class in python?

The problem you're encountering is that looking up a method attribute on a Python 2 class creates an unbound method, it doesn't return the underlying raw function (on Python 3, unbound methods are abolished, and what you're attempting would work just fine). You need to bypass the descriptor protocol machinery that converts from function to unbound method. The easiest way is to use vars to grab the class's attribute dictionary directly:

# Make copy of A's attributes
Bvars = vars(A).copy()
# Modify the desired attribute
Bvars['a'] = 2
# Construct the new class from it
B = type('B', (object,), Bvars)

Equivalently, you could copy and initialize B in one step, then reassign B.a after:

# Still need to copy; can't initialize from the proxy type vars(SOMECLASS)
# returns to protect the class internals
B = type('B', (object,), vars(A).copy())
B.a = 2

Or for slightly non-idiomatic one-liner fun:

B = type('B', (object,), dict(vars(A), a=2))

Either way, when you're done:

B().foo()

will output:

2
10

as expected.

How to create copies of a python object that are not linked to original object?

The simplest way to make a shallow copy of a dictionary is to use the dict's copy method:

In [1]: template = {'thing1': '', 'thing2': '', 'thing3': ''}

In [2]: apile = template.copy()

In [3]: apile['thing1'] = 1

In [4]: apile
Out[4]: {'thing1': 1, 'thing2': '', 'thing3': ''}

In [5]: template
Out[5]: {'thing1': '', 'thing2': '', 'thing3': ''}

 

To make a shallow copy of a list, you can take a slice of the entire list:

copied_list = original_list[:]

 

If you need to clone other things, or if you need a deep copy of a dict of dicts (or a list of dicts, or other mutable objects), you should use the copy module: http://docs.python.org/2/library/copy.html

copy.copy(x)

Return a shallow copy of x.

copy.deepcopy(x)

Return a deep copy of x.

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

 

About your second way: sure, you can create a dict out of another dict, and it will be a copy:

In [23]: p = dict(template)

In [24]: p['thing1'] = 1

In [25]: template
Out[25]: {'thing1': '', 'thing2': '', 'thing3': ''}

In [26]: p
Out[26]: {'thing1': 1, 'thing2': '', 'thing3': ''}

How to make deep copy of a specific(mutable) object?

Generally, Python has a library named 'copy' which implements deepcopy of the basic objects. Try to use from copy import deepcopy and override the __eq__ function of Board.

For more information, take a look at How can I create a copy of an object in Python?



Related Topics



Leave a reply



Submit