Copy
Assignment
assign the reference of an object to the variable

l = ['a', 'b', 'c', 'd']

l2 = l

print id(l), id(l2) # l and l2 have same id

l2[1] = 't' # change both l and l2

print l, l2

			
Shallow Copy
constructs a new compound object, then inserts references of the elements in the original object into it

# all elements are immutable elements, shallow copy and deep copy have the same effect

l = ['a', 'b', 'c', 'd']

l2 = copy.copy(l) # shallow copy

print id(l), id(l2) # l and l2 have different id

l2[1] = 't' # not change l

print l, l2

			

# have mutable elements, shallow copy and deep copy are not same

l = ['a', 'b', [ab', 'ba']]

l2 = copy.copy(l) # shallow copy

print id(l), id(l2) # l and l2 have different id

l2[2][1] = 't' # change both l and l2

print l, l2

			
Deep Copy
constructs a new compound object, then inserts copies of the elements of the original objects into it

# have object elements, shallow copy and deep copy are not same

l = ['a', 'b', [ab', 'ba']]

l2 = copy.deepcopy(l) # deep copy

print id(l), id(l2) # l and l2 have different id

l2[2][1] = 't' # not change l

print l, l2

			
List

l = [1, 2, 3, 4]

# Slicing, shallow copy

l2 = l[:]

# list, shallow copy

l2 = list(l)

# copy.copy(), shallow copy

l2 = copy.copy(l)

# copy.deepcopy(), deep copy

l2 = copy.deepcopy()

			
Dict

# Shallow copy

d = {'Name':'Lin', 'List':[1, 2, 3, 4]

d2 = d.copy()

d2['List'][1] = 10

print d, d2



# Deep copy

d = {'Name':'Lin', 'List':[1, 2, 3, 4]

d2 = copy.deepcopy(d)

d2['List'][1] = 10

print d, d2

			
Tuple

# for immutable elements, shallow copy and deep copy are same

i = (1, 2, (3, 4))

i2 = copy.copy(i)

print id(i), id(i2) # i and i2 have same id

i2 = copy.deepcopy(i)

print id(i), id(i2) # i and i2 have same id



# containing mutable elements

# Shallow copy

l = (1, 2, [3, 4])

l2 = copy.copy(l)

print id(l), id(l2) # l and l2 have same id

# Deep copy

l2 = l+()

print id(l), id(l2) # l and l2 have differnt id

l2 = copy.deepcopy(l)

print id(l), id(l2) # l and l2 have differnt id

			
Shallow copy and deep copy class instance
# Vehicle.py
import copy

class Vehicle(object):
    """Document String: Define a Vehicle class"""

    def __init__(self, brand, year, owners):
        print('Create a Vehicle ...')
        self._brand = brand;
	self._year = year;
        self._owners = owners;

    def __str__(self):
        s = self._brand+' '+str(self._year) + ' owned by: '
        for n in self._owners:
            s = s + ' ' + n
        return s

    def addOwner(self, name):
        self._owners.append(name);

    # shallow copy for copy.copy()
    def __copy__(self):
        print('Call __copy__ ...')
        c = type(self)(self._brand, self._year, [])
        c.__dict__.update(self.__dict__)
        return c

    def __deepcopy__(self, memo):
        print('Call __deepcopy__ ...')
        c = type(self)(self._brand, self._year, [])
        for k, v in self.__dict__.items():
            print(k, v)
            setattr(c, k, copy.deepcopy(v, memo))
        return c
			
# Car.py
import copy
from Vehicle import Vehicle;

class Car(Vehicle):
	"""Define class Car, which is inherit from class Vehicle"""
	def __init__(self, brand, year, owners, model):
	    """Construct"""
	    print "Create Car Object ..."; 
	    super(Car, self).__init__(brand, year, owners);
	    #Vehicle.__init__(self, brand, year);
	    self._model = model;

        # override __str__ in Vehicle
	def __str__(self):
            #return super(Car, self).__str__() + " " + self.model
            return Vehicle.__str__(self) + " " + self._model

        def __copy__(self):
            print('Call __copy__ in Car ...')
            c = type(self)(self._brand, self._year, [], self._model)
            c.__dict__.update(self.__dict__)
            #Vehicle.__init__(c, self._brand, self._year, self._owners)
            return c

        def __deepcopy__(self, memo):
            print('Call __deepcopy__ in Car ...')
            c = type(self)(self._brand, self._year, [], self._model)
            for k, v in self.__dict__.items():
                setattr(c, k, copy.deepcopy(v, memo))
	    #Vehicle.__init__(c, self._brand, self._year, copy.deepcopy(self._owners))
            return c
			
# Copy.py
#!/usr/bin/python

import copy
from Vehicle import Vehicle
from Car import Car

print('--------------------Vehicle-------------------')
v = Vehicle("Buick", 1998, ['Lin', 'Yanhua'])

# shallow copy, call __copy__
v2 = copy.copy(v)

v2.addOwner('Hannah')
print(v) # Buick 1998 Lin Yanhua Hannah
print(v2) # Buick 1998 Lin Yanhua Hannah

# deep copy, call __deepcopy__
v3 = copy.deepcopy(v)

v3.addOwner('Hadley')
print(v)
print(v3)

print('--------------------Car-------------------')
c = Car("Buick", 1998, ['Lin', 'Yanhua'], 'Century')

c2 = copy.copy(c)
c2.addOwner('Hannah')
print(c)
print(c2)

# deep copy, call __deepcopy__ in Car
c3 = copy.deepcopy(c)
c3.addOwner('Hadley')
print(c)
print(c3)
			
Resource
  • stackoverflow
  • Python Course