Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Understanding Deep and Shallow Copy in Python

Tech 1

In Python, there are differences between object assignment, shallow copy, and deep copy. If not used carefully, unexpected results may occur. This article explains these concepts with simple examples.

Object Assignment

Consider the following code:

original_list = ["Alice", 30, ["Python", "Java", "JavaScript"]]
assigned_list = original_list
print(id(original_list))
print(original_list)
print([id(element) for element in original_list])
print(id(assigned_list))
print(assigned_list)
print([id(element) for element in assigned_list])

original_list[0] = "Bob"
original_list[2].append("CSS")
print(id(original_list))
print(original_list)
print([id(element) for element in original_list])
print(id(assigned_list))
print(assigned_list)
print([id(element) for element in assigned_list])

Output: Object Assignment Output

Analysis:

  • A variable original_list is created, pointing to a list object.
  • Assignign original_list to assigned_list makes assigned_list reference the same object (same memory address). In Python, object assignment passes object references.
  • Since both variables point to the same object, modifications to original_list effect assigned_list.
  • Note: Strings are immutable, so modifying original_list[0] creates a new string object at a different address.

Shallow Copy

Now, let's examine shallow copy:

import copy

original_list = ["Alice", 30, ["Python", "Java", "JavaScript"]]
shallow_copied_list = copy.copy(original_list)

print(id(original_list))
print(original_list)
print([id(element) for element in original_list])
print(id(shallow_copied_list))
print(shallow_copied_list)
print([id(element) for element in shallow_copied_list])

original_list[0] = "Bob"
original_list[2].append("CSS")
print(id(original_list))
print(original_list)
print([id(element) for element in original_list])
print(id(shallow_copied_list))
print(shallow_copied_list)
print([id(element) for element in shallow_copied_list])

Output: Shallow Copy Output

Analysis:

  • original_list points to a list object.
  • Using copy.copy() performs a shallow copy, creating a new list object assigned to shallow_copied_list. Thus, shallow_copied_list is not original_list.
  • However, elements within the list are referenced by their original memory addresses, meaning shallow_copied_list[i] is original_list[i].
  • Modifications:
    • The first element (string) is immutable, so changing it creates a new object.
    • The third element (list) is mutable, so changes to original_list[2] affect shallow_copied_list[2].

Shallow copy can also be achieved with:

  • Slice operation [:]
  • Factory functions (e.g., list(), dict(), set())
  • copy.copy()

Deep Copy

Finally, deep copy:

import copy

original_list = ["Alice", 30, ["Python", "Java", "JavaScript"]]
deep_copied_list = copy.deepcopy(original_list)

print(id(original_list))
print(original_list)
print([id(element) for element in original_list])
print(id(deep_copied_list))
print(deep_copied_list)
print([id(element) for element in deep_copied_list])

original_list[0] = "Bob"
original_list[2].append("CSS")
print(id(original_list))
print(original_list)
print([id(element) for element in original_list])
print(id(deep_copied_list))
print(deep_copied_list)
print([id(element) for element in deep_copied_list])

Output: Deep Copy Output

Analysis:

  • original_list points to a list object.
  • Using copy.deepcopy() performs a deep copy, creating a new list object assigned to deep_copied_list. Thus, deep_copied_list is not original_list.
  • Elements are recursively copied, not just referenced. For example, deep_copied_list[2] is not original_list[2].
  • Modifications:
    • Changing the immutable first element creates a new object in original_list.
    • Modifying the mutable third element in original_list does not affect deep_copied_list because they are separate objects.

Special Cases in Copying

There are special cases to consider:

  • Non-container types (e.g., numbers, strings, atomic objects) are not copied; obj is copy.copy(obj) and obj is copy.deepcopy(obj) hold true.
  • Tuples containing only atomic objects cannot be deep copied.

Example: Special Cases

Summary

This article explains object assignment, shallow copy, and deep copy in Python:

  • Object assignment passes object references.
  • Shallow copy (copy.copy()) creates a new object but references the original elements.
  • Deep copy (copy.deepcopy()) recursively copies the container object and all its elements.
  • Non-container types are not copied.
  • Tuples with only atomic objects cannot be deep copied.
Tags: Python

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.