0
grid = np.empty((10,0)).tolist()
coords = grid.copy()
distances = grid.copy()
print(id(grid), id(coords), id(distances))

for i in range(10):
    for j in range(10):
        distances[i].append(i+j)
        coords[i].append([i, j])
print(distances)
print(coords)

I created a nested list for turning into a 2D grid. I want to create two different 2D grid, one containing the coordinate of each element, the other containing the distance of each coordinate from (0,0).

I used the .copy() method twice, and confirmed that coords and distances are in fact different locations in memory. So why does my code output both as the same incorrect list?

Output:

[[0, [0, 0], 1, [0, 1], 2, [0, 2], 3, [0, 3], 4, [0, 4], 5, [0, 5], 6, [0, 6], 7, [0, 7], 8, [0, 8], 9, [0, 9]], [1, [1, 0], 2, [1, 1], 3, [1, 2], 4, [1, 3], 5, [1, 4], 6, [1, 5], 7, [1, 6], 8, [1, 7], 9, [1, 8], 10, [1, 9]], [2, [2, 0], 3, [2, 1], 4, [2, 2], 5, [2, 3], 6, [2, 4], 7, [2, 5], 8, [2, 6], 9, [2, 7], 10, [2, 8], 11, [2, 9]], [3, [3, 0], 4, [3, 1], 5, [3, 2], 6, [3, 3], 7, [3, 4], 8, [3, 5], 9, [3, 6], 10, [3, 7], 11, [3, 8], 12, [3, 9]], [4, [4, 0], 5, [4, 1], 6, [4, 2], 7, [4, 3], 8, [4, 4], 9, [4, 5], 10, [4, 6], 11, [4, 7], 12, [4, 8], 13, [4, 9]], [5, [5, 0], 6, [5, 1], 7, [5, 2], 8, [5, 3], 9, [5, 4], 10, [5, 5], 11, [5, 6], 12, [5, 7], 13, [5, 8], 14, [5, 9]], [6, [6, 0], 7, [6, 1], 8, [6, 2], 9, [6, 3], 10, [6, 4], 11, [6, 5], 12, [6, 6], 13, [6, 7], 14, [6, 8], 15, [6, 9]], [7, [7, 0], 8, [7, 1], 9, [7, 2], 10, [7, 3], 11, [7, 4], 12, [7, 5], 13, [7, 6], 14, [7, 7], 15, [7, 8], 16, [7, 9]], [8, [8, 0], 9, [8, 1], 10, [8, 2], 11, [8, 3], 12, [8, 4], 13, [8, 5], 14, [8, 6], 15, [8, 7], 16, [8, 8], 17, [8, 9]], [9, [9, 0], 10, [9, 1], 11, [9, 2], 12, [9, 3], 13, [9, 4], 14, [9, 5], 15, [9, 6], 16, [9, 7], 17, [9, 8], 18, [9, 9]]]
  • 2
    You created a shallow copy, which means that all top-level references are shared. If you don't want that, then create a deep copy. See `copy.deepcopy` for details. – Tom Karzes Jun 22 '22 at 10:26
  • Does this answer your question? [How do I clone a list so that it doesn't change unexpectedly after assignment?](https://stackoverflow.com/questions/2612802/how-do-i-clone-a-list-so-that-it-doesnt-change-unexpectedly-after-assignment) – Tom Karzes Jun 22 '22 at 10:28
  • @TomKarzes I see, that would explain it. So what is the point of a shallow copy then if each copy can't be modified individually? – shadow_integration Jun 22 '22 at 11:32
  • In many cases you only need a shallow copy, and indeed want a shallow copy. A deep copy should only be used when absolutely necessary. – Tom Karzes Jun 22 '22 at 12:08
  • A shallow copy is useful when you know you won't modify any data inside the list. Only the list itself. For example: a list of strings. Strings are immutable objects. If you copy the list to another variable, and append data to a string inside the copy, the original list won't have any modified strings. So, in this case, a shallow copy gets the job done. – Carl HR Jun 22 '22 at 19:12
  • In your example, as you need to modify each row inside the copies of `grid`, a deepcopy is necessary. However, you could assign a secondary shallow copy for each row, right after the first for-loop statement. This way you wouldn't mix `distances` and `coords` data structures anymore. – Carl HR Jun 22 '22 at 19:28
  • Now, why @TomKarzes is saying that `deepcopy` is bad? Simple. Imagine a complex data structure with many and many depth levels. Deepcopy would create a copy for each single object at any depth level of this structure. It would iterate over all of them, which takes a lot of memory for caching data, and time. However, if you just needed a copy only until depth 2 for example, creating your own iteration using shallow copies would be the best choice for more efficiency and less complexity. – Carl HR Jun 22 '22 at 19:35

0 Answers0