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