jackskis jackskis - 4 months ago 16
Python Question

Does appending a list slice back to the original list just copy the addresses?

If I have a list of objects as such in Python:

li = [obj1, obj2, obj3, ob4, obj5]


And I append the last two objects to the end of the list again:

li.extend(li[-2:])


Do duplicates in
li
now have the same or different addresses? If I make changes to one of the elements of the array that has been appended to the end of the list
li
, will the duplicate at the end also change? Is there a better way to preform this copy if so?

Answer

The same addresses - you can check this with id. If the elements of the list are mutable, then modifying one will modify the other. If the elements of the list are immutable, then you cannot modify them.

li = [1, 1.0, None, ['a', 'b'], ('c', 'd')]

li.extend(li[-2:])
print(li)
# outputs [1, 1.0, None, ['a', 'b'], ('c', 'd'), ['a', 'b'], ('c', 'd')]

li[-2].pop()
print(li)
# outputs [1, 1.0, None, ['a'], ('c', 'd'), ['a'], ('c', 'd')]
# Note that elemnts at indices -2 and -4 have changed since id(li[-2]) == id(li[-4])

print(id(li[-1]) == id(li[-3]))
# True

To add deep copies, you can use the copy module.

li = [1, 1.0, None, ['a', 'b'], ('c', 'd')]

li.extend(list(map(copy.deepcopy, li[-2:])))
print(li)
# outputs [1, 1.0, None, ['a', 'b'], ('c', 'd'), ['a', 'b'], ('c', 'd')]

li[-2].pop()
print(li)
# outputs [1, 1.0, None, ['a', 'b'], ('c', 'd'), ['a'], ('c', 'd')]
# Note that only the list at index -2 has changed since id(li[-2]) != id(li[-4])

Note that for immutable objects, copy.deepcopy does not make a copy of the object unless that object has references to other mutable objects. So in the last list id(li[-1]) == id(li[-3]).

Comments