Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shallow copy of list[:]

Tags:

python

copy

According to this Official Documentation:

list[:]

creates a new list by shallow copy. I performed following experiments:

>>> squares = [1, 4, 9, 16, 25]
>>> new_squares = square[:]
>>> squares is new_squares
False
>>> squares[0] is new_squares[0]
True
>>> id(squares)
4468706952
>>> id(new_squares)
4468425032
>>> id(squares[0])
4466081856
>>> id(new_squares[0])
4466081856

All here look good! new_square and square are different object (list here), but because of shallow copy, they share the same content. However, the following results make me confused:

>>> new_squares[0] = 0
>>> new_squares
[0, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]

I update new_square[0] but square is not affected. I checked their ids:

>>> id(new_squares[0])
4466081824
>>> id(squares[0])
4466081856

You can find that the id of squares[0] keeps no change but the id of new_squares[0] changes. This is quite different from the shallow copy I have understood before.

Could anyone can explain it? Thanks!

like image 544
zchenkui Avatar asked Nov 07 '22 18:11

zchenkui


1 Answers

You have a list object that represents a container of other objects. When you do a shallow copy, you create a new list object (as you see) that contains references to the same objects that the original list contained.

new_squares[0] = 0 is an assignment. You're saying "set a new object at the 0th index of the list". Well, the lists are now separate objects and you're flatly replacing the object held at an index of the copy. It wouldn't matter if the object at the 0th index was mutable either, since you're just replacing the reference that the list object holds.

If the list instead contained a mutable object and you were to modify that object in place without completely changing what object is stored in that index, then you would see the change across both lists. Not because the lists are in any way linked, but because they hold reference to a mutable object that you have now changed.

This can be illustrated below, where I can separately make modifications to the shallow-copied list, and also cause a mutable object to change across both lists, even when that mutable object is now at difference indices between the two.

# MAKING A CHANGE TO THE LIST
a = [1, {'c': 'd'}, 3, 4]
b = a[:]
b.insert(0, 0)

print(a)
print(b)
print()

# MODIFYING A MUTABLE OBJECT INSIDE THE LIST
a[1]['c'] = 'something_else'

print(a)
print(b)
like image 146
roganjosh Avatar answered Nov 15 '22 12:11

roganjosh