E0_copy is not a deep copy. You don't make a deep copy using list(). (Both list(...) and testList[:] are shallow copies, as well as testList.copy().)

You use copy.deepcopy(...) for deep copying a list.

copy.deepcopy(x[, memo])

Return a deep copy of x.

See the following snippet -

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b   # b changes too -> Not a deepcopy.
[[1, 10, 3], [4, 5, 6]]

Now see the deepcopy operation

>>> import copy
>>> b = copy.deepcopy(a)
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
>>> a[0][1] = 9
>>> a
[[1, 9, 3], [4, 5, 6]]
>>> b    # b doesn't change -> Deep Copy
[[1, 10, 3], [4, 5, 6]]

To explain, list(...) does not recursively make copies of the inner objects. It only makes a copy of the outermost list, while still referencing the same inner lists, hence, when you mutate the inner lists, the change is reflected in both the original list and the shallow copy. You can see that shallow copying references the inner lists by checking that id(a[0]) == id(b[0]) where b = list(a).

Answer from Sukrit Kalra on Stack Overflow
🌐
Python
docs.python.org β€Ί 3 β€Ί library β€Ί copy.html
copy β€” Shallow and deep copy operations
A shallow copy constructs a new ... found in the original. A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original....
🌐
GeeksforGeeks
geeksforgeeks.org β€Ί python β€Ί array-copying-in-python
Array Copying in Python - GeeksforGeeks
April 30, 2025 - Explanation: A shallow copy creates ... copy of a, meaning changes in a will reflect in b. Deep copy is a process in which the copying process occurs recursively....
Discussions

python - Deep copy of a np.array of np.array - Stack Overflow
I have a numpy array of different numpy arrays and I want to make a deep copy of the arrays. I found out the following: import numpy as np pairs = [(2, 3), (3, 4), (4, 5)] array_of_arrays = np.ar... More on stackoverflow.com
🌐 stackoverflow.com
Do I need to be using deepcopy with numpy arrays in this situation?
The short answer is that if you have, say, a numpy array of ints, floats, etc (which is usually) and you want to make a separate copy where the two will not interact in any way (which is what it sounds like), there's no need to deepcopy, and you can just use the array.copy() method. Long version: You are also correct on copy vs deepcopy. If you use copy on, say, a list (more on arrays later), you will get a different list containing the same elements of the original. So: l = [[1], [2]] l2 = copy.copy(l) # l2 is different from l # The sublists inside l2 are the same as the ones in l l2[0] = 42 # l unchanged, you modified l2 which is different l2[1][0] = 1337 # reflected in l, because l2[1] is the same as l[1] So in this case, if you didn't want l2[1][0] = 1337 to be reflected in l, you'd use deepcopy. This would ensure that the sublists are different, as well as the outer list. However, if the contents of l are say, floats or ints, then this doesn't matter. Floats are immutable - you can't change em. What you might think of as modifying a float is actually creating a new float and putting that new float somewhere. So: l = [1.2, 3.4] l2 = l.copy() # same as copy.copy(l) # The elements of l2 are still the same as of l as before. But: l2[0] += 7 # does not actually modify the # float 1.2, but creates a new # float 8.2 and assigns that to # l2[0] - which modifies l2, which # is different from l, so l is unchanged So in this case deepcopy is not necessary to make l and l2 behave completely distinctly (though it doesn't hurt anything - might use a bit more ram depending on what types are in l). Numpy arrays are almost certainly a bit different though. For one thing, a single numpy array with shape (5, 5), say, is not actually an array of arrays, but a single sequence of length 25 that uses math to let you use double indexing. Also, under the hood numpy arrays have byte buffers representing whatever types, so I strongly suspect that array.copy just copies that buffer (at least if it's an array of numbers). So it's possible that it's not really the same rules as lists of objects anyway. But .copy is certainly sufficient for what you want. More on reddit.com
🌐 r/learnpython
1
1
April 21, 2023
How to make a copy of a 2D array in Python? - Stack Overflow
X is a 2D array. I want to have a new variable Y that which has the same value as the array X. Moreover, any further manipulations with Y should not influence the value of the X. It seems to me so More on stackoverflow.com
🌐 stackoverflow.com
Python copy.copy() appears to make a deep copy
The difference between a deep copy and a shallow copy is whether or not nested mutable structures are (recursively) copied (deep) or just referenced (shallow). All elements of your list are immutable. Therefore, there is no difference between a shallow and a deep copy. A proper demonstration of the difference is this: import copy my_list = [['first'], ['second'], ['third']] my_deep_copy = copy.deepcopy(my_list) my_deep_copy[1][0] = 'new value' print(my_list) my_shallow_copy = copy.copy(my_list) my_shallow_copy[1][0] = 'new value' print(my_list) Note how it requires nested mutable structures. More on reddit.com
🌐 r/learnpython
10
90
October 17, 2022
Top answer
1 of 10
416

E0_copy is not a deep copy. You don't make a deep copy using list(). (Both list(...) and testList[:] are shallow copies, as well as testList.copy().)

You use copy.deepcopy(...) for deep copying a list.

copy.deepcopy(x[, memo])

Return a deep copy of x.

See the following snippet -

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b   # b changes too -> Not a deepcopy.
[[1, 10, 3], [4, 5, 6]]

Now see the deepcopy operation

>>> import copy
>>> b = copy.deepcopy(a)
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
>>> a[0][1] = 9
>>> a
[[1, 9, 3], [4, 5, 6]]
>>> b    # b doesn't change -> Deep Copy
[[1, 10, 3], [4, 5, 6]]

To explain, list(...) does not recursively make copies of the inner objects. It only makes a copy of the outermost list, while still referencing the same inner lists, hence, when you mutate the inner lists, the change is reflected in both the original list and the shallow copy. You can see that shallow copying references the inner lists by checking that id(a[0]) == id(b[0]) where b = list(a).

2 of 10
104

In Python, there is a module called copy with two useful functions:

import copy
copy.copy()
copy.deepcopy()

copy() is a shallow copy function. If the given argument is a compound data structure, for instance a list, then Python will create another object of the same type (in this case, a new list) but for everything inside the old list, only their reference is copied. Think of it like:

newList = [elem for elem in oldlist]

Intuitively, we could assume that deepcopy() would follow the same paradigm, and the only difference is that for each elem we will recursively call deepcopy, (just like mbguy's answer)

but this is wrong!

deepcopy() actually preserves the graphical structure of the original compound data:

a = [1,2]
b = [a,a] # there's only 1 object a
c = deepcopy(b)

# check the result
c[0] is a # False, a new object a_1 is created
c[0] is c[1] # True, c is [a_1, a_1] not [a_1, a_2]

This is the tricky part: during the process of deepcopy(), a hashtable (dictionary in Python) is used to map each old object ref onto each new object ref, which prevents unnecessary duplicates and thus preserves the structure of the copied compound data.

Official docs

Top answer
1 of 7
34
import numpy as np
import copy

pairs = [(2, 3), (3, 4), (4, 5)]
array_of_arrays = np.array([np.arange(a*b).reshape(a,b) for (a, b) in pairs])

a = copy.deepcopy(array_of_arrays)

Feel free to read up more about this here.

Oh, here is simplest test case:

a[0][0,0]
print a[0][0,0], array_of_arrays[0][0,0]
2 of 7
5
In [276]: array_of_arrays
Out[276]: 
array([array([[0, 1, 2],
       [3, 4, 5]]),
       array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]]),
       array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])], dtype=object)

array_of_arrays is dtype=object; that means each element of the array is a pointer to an object else where in memory. In this case those elements are arrays of different sizes.

a = array_of_arrays[:]

a is a new array, but a view of array_of_arrays; that is, it has the same data buffer (which in this case is list of pointers).

b = array_of_arrays[:][:] 

this is just a view of a view. The second [:] acts on the result of the first.

c = np.array(array_of_arrays, copy=True)

This is the same as array_of_arrays.copy(). c has a new data buffer, a copy of the originals

If I replace an element of c, it will not affect array_of_arrays:

c[0] = np.arange(3)

But if I modify an element of c, it will modify the same element in array_of_arrays - because they both point to the same array.

The same sort of thing applies to nested lists of lists. What array adds is the view case.

d = np.array([np.array(x, copy=True) for x in array_of_arrays])

In this case you are making copies of the individual elements. As others noted there is a deepcopy function. It was designed for things like lists of lists, but works on arrays as well. It is basically doing what you do with d; recursively working down the nesting tree.

In general, an object array is like list nesting. A few operations cross the object boundary, e.g.

 array_of_arrays+1

but even this effectively is

np.array([x+1 for x in array_of_arrays])

One thing that a object array adds, compared to a list, is operations like reshape. array_of_arrays.reshape(3,1) makes it 2d; if it had 4 elements you could do array_of_arrays.reshape(2,2). Some times that's handy; other times it's a pain (it's harder to iterate).

🌐
Delft Stack
delftstack.com β€Ί home β€Ί howto β€Ί numpy β€Ί python numpy deep copy
NumPy Deep Copy | Delft Stack
March 11, 2025 - In this article, we will explore two main methods for achieving deep copies of NumPy arrays in Python: using the built-in copy.deepcopy() function and a user-defined approach.
🌐
GeeksforGeeks
geeksforgeeks.org β€Ί copy-python-deep-copy-shallow-copy
Deep Copy and Shallow Copy in Python - GeeksforGeeks
In Python, there are several ways to copy arrays, each with different behaviors. The three main methods for copying arrays are:Simply using the assignment operator.Shallow CopyDeep Copy1. Assigning the ArrayWe can create a copy of an array by using the assignment operator (=).
Published: December 10, 2024
Find elsewhere
🌐
Real Python
realpython.com β€Ί python-copy
How to Copy Objects in Python: Shallow vs Deep Copy Explained – Real Python
1 week ago - In this case, the "h" argument in the array.array() call specifies that the array will store numbers as two-byte signed integers. As you can see, a Python array aggregates scalar numbers into a flat sequence, whereas a list and tuple can contain deeply nested structures arranged in a particular way.
🌐
Tutorialspoint
tutorialspoint.com β€Ί python β€Ί python_copy_arrays.htm
Python - Copy Arrays
To create another physical copy of an array, we use another module in Python library, named copy and use deepcopy() function in the module.
🌐
Reddit
reddit.com β€Ί r/learnpython β€Ί do i need to be using deepcopy with numpy arrays in this situation?
r/learnpython on Reddit: Do I need to be using deepcopy with numpy arrays in this situation?
April 21, 2023 -

I've done a ton of reading about this and I sort of know the difference between the two, but I still don't know when I need to use copy.copy() vs copy.deepcopy(). It seems like copy.copy() makes a new object of the "container" (for instance, if it is a list then you get a new list object) but then populates this container with the references to the original element objects (so each element in the two different lists point to the same spot in memory).

Essentially, my question is that I have a bunch of numpy arrays and I don't think I'm using copy correctly (or if I need ot be using it at all). It seems like if I am only doing assignments or using these values to set other values (eg output = self.weights*input or whatever) then I don't need to make copies (its fine that the references point to the same spot in memory since I just need read not write access), but if I am doing things like increments / decrements or setting the new value based on the previous value, then I would be changing the values in memory and these are shared by all my objects? Some code:

For instance, let's say I have some Parent class and it has its children Child objects and the parent sends its models to the children and the children update the models based on their own data. Specifically, each child should get (a copy?) the parent's weight matrix (numpy array) to use as initialization, and then start updating its own matrix (not shared with any other children or the parent).

parent = Parent()
child1 = Child()
child2 = Child()
...
childN = Child()

for child in children_list:
    child.weights = parent.weights  # copy? deepcopy?

for child in children_list:
    for _ in num_grad_steps:
        child.weights -= child.learning_rate * child.gradient(child.weights, child.input_data)
    
    # Send the updated weights back to the parent
    parent.new_weights_list.append(child.weights)

In this case, child.weights is being updated by each child (note I don't want a single matrix that is updated by all children, I want one matrix as initialization, then every child runs with it so I end up with N unique final matrices), and if it is either just the same object (basic assignment: child.weights = self.weights) or just a shallow copy (child.weights = copy.copy(parent.weights)) then FOR ALL THE CHILDREN the weights are shared instead of each child getting the same initial matrix and privately updating its own copy, right? If I instead switch this to child.weights = copy.deepcopy(parent.weights) then I think this fixes it, but since my weights matrix is pretty large this just takes an extremely long time to run (and it seems like I'm missing something, like it shouldn't be this hard. I feel like code I see online in similar applications doesn't do this, but many don't have the weights distributed across so many objects at once I guess?). Do I need to be using deepcopy or is there something I'm missing? Greatly appreciate any help!

Top answer
1 of 1
2
The short answer is that if you have, say, a numpy array of ints, floats, etc (which is usually) and you want to make a separate copy where the two will not interact in any way (which is what it sounds like), there's no need to deepcopy, and you can just use the array.copy() method. Long version: You are also correct on copy vs deepcopy. If you use copy on, say, a list (more on arrays later), you will get a different list containing the same elements of the original. So: l = [[1], [2]] l2 = copy.copy(l) # l2 is different from l # The sublists inside l2 are the same as the ones in l l2[0] = 42 # l unchanged, you modified l2 which is different l2[1][0] = 1337 # reflected in l, because l2[1] is the same as l[1] So in this case, if you didn't want l2[1][0] = 1337 to be reflected in l, you'd use deepcopy. This would ensure that the sublists are different, as well as the outer list. However, if the contents of l are say, floats or ints, then this doesn't matter. Floats are immutable - you can't change em. What you might think of as modifying a float is actually creating a new float and putting that new float somewhere. So: l = [1.2, 3.4] l2 = l.copy() # same as copy.copy(l) # The elements of l2 are still the same as of l as before. But: l2[0] += 7 # does not actually modify the # float 1.2, but creates a new # float 8.2 and assigns that to # l2[0] - which modifies l2, which # is different from l, so l is unchanged So in this case deepcopy is not necessary to make l and l2 behave completely distinctly (though it doesn't hurt anything - might use a bit more ram depending on what types are in l). Numpy arrays are almost certainly a bit different though. For one thing, a single numpy array with shape (5, 5), say, is not actually an array of arrays, but a single sequence of length 25 that uses math to let you use double indexing. Also, under the hood numpy arrays have byte buffers representing whatever types, so I strongly suspect that array.copy just copies that buffer (at least if it's an array of numbers). So it's possible that it's not really the same rules as lists of objects anyway. But .copy is certainly sufficient for what you want.
🌐
Note.nkmk.me
note.nkmk.me β€Ί home β€Ί python
Shallow and Deep Copy in Python: copy(), deepcopy() | note.nkmk.me
May 13, 2023 - In Python, you can make a shallow and deep copy using the copy() and deepcopy() functions from the copy module. A shallow copy can also be made with the copy() method of lists, dictionaries, and so on ...
🌐
TestDriven.io
testdriven.io β€Ί tips β€Ί c55f0591-8fcf-473c-bb46-4fb1279b4d4a
Tips and Tricks - Python deep copy via copy.deepcopy() | TestDriven.io
import copy house = { "width": 12, "length": 8, "height": 3.5, "doors": [ {"type": " ENTRANCE", "width": 0.9, "height": 2.2}, {"type": "BACK DOOR", "width": 0.7, "height": 2.0}, ], } same_house = copy.deepcopy(house) print(house) print(same_house) print(house == same_house) """ {'width': 12, 'length': 8, 'height': 3.5, 'doors': [{'type': ' ENTRANCE', 'width': 0.9, 'height': 2.2}, {'type': 'BACK DOOR', 'width': 0.7, 'height': 2.0}]} {'width': 12, 'length': 8, 'height': 3.5, 'doors': [{'type': ' ENTRANCE', 'width': 0.9, 'height': 2.2}, {'type': 'BACK DOOR', 'width': 0.7, 'height': 2.0}]} True ""
🌐
Programiz
programiz.com β€Ί python-programming β€Ί shallow-deep-copy
Python Shallow Copy and Deep Copy (With Examples)
The deep copy creates independent copy of original object and all its nested objects.
🌐
Aims
python.aims.ac.za β€Ί pages β€Ί cp_mutable_objs.html
21. Be careful: copying arrays, lists (and more) β€” AIMS Python 0.7 documentation
import copy A = <some array, list or other mutable object> B = copy.deepcopy( A ) In our own thought-processing and algorithm generation, we might picture the variable A as representing the whole array/list/etc.---that is fine. But when it comes to implementing the program, we need to be aware that it is something different to Python (it is just the starting point reference of the object), so that we can deal with it appropriately.
🌐
Plain English
python.plainenglish.io β€Ί shallow-copy-and-deep-copy-in-python-numpy-8861e0870c5f
Shallow Copy and Deep Copy in Python NumPy: Python Data Science Complete Course
May 6, 2022 - How to make a new reference to the same memory location of the NumPy array or a stand-alone copy of the NumPy array, by using a shallow or deep copy.
🌐
Vultr Docs
docs.vultr.com β€Ί python β€Ί third party β€Ί numpy β€Ί copy()
Python Numpy copy() - Create Array Copy
November 7, 2024 - Unlike using copy(), changing the shallow copy also affects the original array. This demonstrates the difference between deep copying (copy()) and shallow copying (slicing). Use the copy() function when you need to preserve the original data without any unintentional modifications due to variable referencing in Python.
🌐
Dataquest
dataquest.io β€Ί home β€Ί blog β€Ί how to copy a list in python (5 techniques w/ examples)
How to Copy a List in Python (5 Techniques w/ Examples)
March 6, 2023 - As mentioned earlier, the recursive deep copy produces a truly independent copy of the original list, which is why the inner lists in the original and copied lists point to two different memory locations. Obviously, any changes made to the inner list of one won't be reflected in the other. This tutorial discussed several different ways for copying a list in Python, such as the assignment operator, list slicing syntax, list.copy(), copy.copy(), and copy.deepcopy functions.
🌐
GitHub
gist.github.com β€Ί a050c5b3e6a4866b8949
Deep Copy a 2d array in python Β· GitHub
Deep Copy a 2d array in python. GitHub Gist: instantly share code, notes, and snippets.
🌐
Quora
quora.com β€Ί What-is-the-difference-between-a-shallow-and-deep-copy-of-an-array-in-Python
What is the difference between a shallow and deep copy of an array in Python? - Quora
Answer: Shallow Copy A shallow copy is a copy of an object that stores the reference of the original elements. It creates the new collection object and then occupying it with reference to the child objects found in the original. It makes copies of the nested objects' reference and doesn't creat...