Code 13: Shallow or Deep?

Learning to copy the right way
coding
python
Author

Tony Phung

Published

October 22, 2024

1. Methods: 3 Flavours

This post will through 3 different methods to copy a list and see the differences.

1.1 Assignment:

  • Code: =
  • Creates a new variable name, not a new object.
  • New varaible name references for the same original object.

1.2 Shallow Copy:

  • Code: copy.copy()
  • Creates a new top level object
  • Maintains original references (i.e. not new copies) of same objects

1.3 Deep Copy:

  • Code: copy.deepcopy()
  • Creates a new object
  • Creates new copies recursively of all inner objects

2. Analysis

High-level Steps:

  • 2.1 Create Cat Class and Object
  • 2.2 Create Cat List and append Cat Object milo
  • 2.3 Create Copies Cat List with Each Method
  • 2.4 Are each milo object new or copies of original milo?
  • 2.5 Update milo to Milo
  • 2.6 Results of milo the Different Methods

2.1 Create Cat Class and Object

class Cat():
    def __init__(self, name: str):
        self.name = name
        
    def __repr__(self) -> str:
        return self.name

Milo_obj = Cat(name="milo")
print(f"id: [{id(Milo_obj)}]")
id: [140517113061744]

2.2 Create Cat List and append Cat Object milo

import copy
listcats = ['Oreo','Lilo','Wasabi',Milo_obj]
listcats
['Oreo', 'Lilo', 'Wasabi', milo]

2.3 Create Copies of Cat List with Each Method

Assignment = results:

  • Gives a reference back to same origin object (same id:140517134247168)

Others results (.copy, .deepcopy, :):

  • create a new (top-level) object (difference ids):
    • Note: Only compared ids of outer layer list objects. We need to see the individual items within the list (next section).
listcats_copy_assn      = listcats               
listcats_copy_shallow   = copy.copy(listcats)    
listcats_copy_deep      = copy.deepcopy(listcats)
listcats_copy_slice     = listcats[:]            
print(f"[id:{id(listcats)}] listcats_og: {listcats}")                       
print(f"[id:{id(listcats_copy_assn)}] listcats_cpy_assn: {listcats_copy_assn}")       
print(f"[id:{id(listcats_copy_shallow)}] listcats_cpy_shallow: {listcats_copy_shallow}") 
print(f"[id:{id(listcats_copy_deep)}] listcats_cpy_deep: {listcats_copy_deep}")      
print(f"[id:{id(listcats_copy_slice)}] listcats_cpy_slice: {listcats_copy_slice}")
[id:140517134247168] listcats_og: ['Oreo', 'Lilo', 'Wasabi', milo]
[id:140517134247168] listcats_cpy_assn: ['Oreo', 'Lilo', 'Wasabi', milo]
[id:140517124516096] listcats_cpy_shallow: ['Oreo', 'Lilo', 'Wasabi', milo]
[id:140517110270272] listcats_cpy_deep: ['Oreo', 'Lilo', 'Wasabi', milo]
[id:140517124392064] listcats_cpy_slice: ['Oreo', 'Lilo', 'Wasabi', milo]

2.4 Are each milo object new or copies of original?

Shallow copies keeps the same references:

  • All copy methods (except deepcopy()) have the same milo object as original id: [140517113061744]

Deep copies creates new objects: creates new id’s

print(f"[{id(listcats[3])}]-[milo id] of [listcats_og]: {listcats[3]}")                       
print(f"[{id(listcats_copy_assn[3])}]-[milo id] of [listcats_cpy_assn]: {listcats_copy_assn[3]}")       
print(f"[{id(listcats_copy_shallow[3])}]-[milo id] of [listcats_cpy_shallow]: {listcats_copy_shallow[3]}") 
print(f"[{id(listcats_copy_deep[3])}]-[milo id] of [listcats_cpy_deep]: {listcats_copy_deep[3]}")      
print(f"[{id(listcats_copy_slice[3])}]-[milo id] of [listcats_cpy_slice]: {listcats_copy_slice[3]}")    
[140517113061744]-[milo id] of [listcats_og]: milo
[140517113061744]-[milo id] of [listcats_cpy_assn]: milo
[140517113061744]-[milo id] of [listcats_cpy_shallow]: milo
[140517115254800]-[milo id] of [listcats_cpy_deep]: milo
[140517113061744]-[milo id] of [listcats_cpy_slice]: milo

2.5 Update milo to Milo

Milo_obj.name="Milo"
Milo_obj
Milo

2.6 Results of milo the Different Methods

As expected:

  • The deepcopy list milo has not updated (since its a new object, i.e. new object id: 140517115254800)
  • All other methods do update original milo since references are maintained, rather than creating new objects (i.e. same object id: 140517113061744)
print(f"[{id(listcats[3])}]-[milo id] of [listcats_og]: {listcats[3]}")                       
print(f"[{id(listcats_copy_assn[3])}]-[milo id] of [listcats_cpy_assn]: {listcats_copy_assn[3]}")       
print(f"[{id(listcats_copy_shallow[3])}]-[milo id] of [listcats_cpy_shallow]: {listcats_copy_shallow[3]}") 
print(f"[{id(listcats_copy_deep[3])}]-[milo id] of [listcats_cpy_deep]: {listcats_copy_deep[3]}")      
print(f"[{id(listcats_copy_slice[3])}]-[milo id] of [listcats_cpy_slice]: {listcats_copy_slice[3]}")    
[140517113061744]-[milo id] of [listcats_og]: Milo
[140517113061744]-[milo id] of [listcats_cpy_assn]: Milo
[140517113061744]-[milo id] of [listcats_cpy_shallow]: Milo
[140517115254800]-[milo id] of [listcats_cpy_deep]: milo
[140517113061744]-[milo id] of [listcats_cpy_slice]: Milo