# Topic covered
* Deepcopy and Shallow copy
* Value equality vs identity

Deepcopy and Shallow copy

  • In case of shallow copy, a reference of object is copied in other object.
    • It means that any changes made to the copied object do reflect in the original object
    • External object id changes but Internal object id remains same
  • In case of deep copy, a copy of object is copied in other object.
    • It means that any changes made to the copied object do not reflect in the original object
    • External and internal object ids changes

Generally used

[:] and copy() –> both does shallow copy

l1 = [0, 2, 4, 6, 8]

l2 = l1
l1 is l2 # True
# i.e id(l1) == id(l2)

l3 = l2 [:]
l3 is l2  # False
# i.e id(l2) != id(l3)

l4 = l2.copy()
l4 is l2 # False
# i.e id(l2) != id(l4)

Deepcopy and shallow copy

copy.copy() –> import copy

import copy

l5 = [1, 2, [4, 5, 7], 8]
l6 = copy.copy(l5) 
print(l5)

l5[2][2] = 9
l5[3] = 10
print(l5)
print(l6)

# OP
# [1, 2, [4, 5, 7], 8]
# [1, 2, [4, 5, 9], 10]
# [1, 2, [4, 5, 9], 8]
# NOTE:
  * l5: Changed made --> Int and ext obj elements
  * l6: Int obj element changes, ext obj element remains same

print(l5 is l6)
# False
print(l5[2] is l6[2])
# True  -->  internal list point to same obj

copy.deepcopy()

l7 = [1, 2, [4, 5, 8], 11]
l8 = copy.deepcopy(l7)
print(l7 is l8)
print(l7)
l7[2][2] = 9
l7[3] = 10

print(l7)
print(l8)

# False
# [1, 2, [4, 5, 8], 11]
# [1, 2, [4, 5, 9], 10] 
# [1, 2, [4, 5, 8], 11]
# NOTE:
  * l7: On int and ext obj's element change
  * l8: Nothing changes

print(l7 is l8)
# False
print(l7[2] is l8[2])
# False

Value equality vs identity

  • Value –> equivalent contents
  • Identity –> same object

Binding Names to Objects

p = [1,2,3]
q = [1,2,3] 
p == q  # --> True    --> val is same
p is q  # --> False   --> not same obj

a = "first"
b = "first"
a is b # --> True
  • NOTE:
    • Immutable object (str, int tuple) refers to same obj if values are same
    • Mutable obj always create new object

Pass by object reference

  • Python uses neither Pass by Value nor Pass by Reference
  • But it uses Pass by Object Reference

Python code to demonstrate –> call by value

def test(string):
    string = "New value"
    print("Inside Function:", string)
string = "Old value"
test(string)
print("Outside Function:", string)

# Inside Function: New value
# Outside Function: Old value
  • Immutable objects – is used
  • So, a new object is created inside_fxn, which is different form outer the fxn

Python code to demonstrate –> call by reference

def add_more(mylist):
    mylist.append(50)
    print("Inside Function", mylist)
mylist = [10, 20, 30, 40]
add_more(mylist)
print("Outside Function:", mylist)

# Inside Function [10, 20, 30, 40, 50]
# Outside Function: [10, 20, 30, 40, 50]
  • Mutable object – is used
  • Inside_fxn new value is assigned to the same object, So, we get modified value in outside_fxn

NOTE:

  • By above example we can say python used pass by object reference
  • It depends on the object type weather values or reference be used.

Reference