Search code examples
pythonarraysdeep-copyshallow-copy

Does the nums array make a deep copy of letters[2:5] = ['C', 'D', 'E']?


I am learning shallow v.s. deep copying a list in Python. I learned that there're two ways to create copies that have the original values unchanged and only modify the new values or vice versa. They're shallow copy and deep copy.

Besides Copy.copy() and Copy.deepcopy(), I learned slice operators can be use for shallow and deep copying a list. From the Python official documentation, I was able to find information that doing correct_rgba = rgba[:], correct_rgba makes a shallow copy of rgba.

Example 1.

rgba = ["Red", "Green", "Blue", "Alph"]
correct_rgba = rgba[:]
correct_rgba[-1] = "Alpha"
correct_rgba  # ["Red", "Green", "Blue", "Alpha"]
rgba  # ["Red", "Green", "Blue", "Alph"]

However, I couldn't find information to confirm whether Assignment to Slices is a deep copy. Here is an example found on the same Python documentation.

Example 2.

letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
letters[2:5] = ['C', 'D', 'E']
letters  # ['a', 'b', 'C', 'D', 'E', 'f', 'g']
letters[:] = []
letters  # []

My questions:

(1) Does letters[2:5] deep copy ['C', 'D', 'E']? Does letters[:] deep copy []?

(2) How do I test to find out whether a list is a shallow or deep copy?


Solution

  • Let's break down your questions and concerns:

    (1) Does letters[2:5] deep copy ['C', 'D', 'E']? Does letters[:] deep copy []?

    No, neither of these operations performs a deep copy.

    • letters[2:5] = ['C', 'D', 'E'] is an assignment to a slice of the original list. It replaces the elements at indices 2, 3, and 4 with the new values, but it doesn't create a new copy of the list. The original list is modified in place.
    • letters[:] = [] is also an assignment to a slice, but this time it replaces the entire list with an empty list. Again, this modifies the original list, it doesn't create a new copy.

    (2) How do I test to find out whether a list is a shallow or deep copy?

    To determine whether a list is a shallow or deep copy, you can use the following methods:

    Shallow copy:

    • Use the id() function to check if the original list and the copied list have the same memory address. If they do, it's a shallow copy.
    • Modify the original list and check if the copied list is affected. If it is, it's a shallow copy.

    Example:

    original_list = [[1, 2], [3, 4]]
    shallow_copy = original_list[:]
    print(id(original_list) == id(shallow_copy))  # True
    original_list[0][0] = 10
    print(shallow_copy)  # [[10, 2], [3, 4]] (affected by original list)
    

    Deep copy:

    • Use the id() function to check if the original list and the copied list have different memory addresses. If they do, it might be a deep copy.
    • Modify the original list and check if the copied list is not affected. If it's not, it's likely a deep copy.

    Example:

    import copy
    original_list = [[1, 2], [3, 4]]
    deep_copy = copy.deepcopy(original_list)
    print(id(original_list) != id(deep_copy))  # True
    original_list[0][0] = 10
    print(deep_copy)  # [[1, 2], [3, 4]] (not affected by original list)
    

    Keep in mind that these methods are not foolproof, and there might be edge cases where they don't accurately determine whether a copy is shallow or deep. However, they should give you a good indication in most cases.