For immutable objects, there is no need for copying because
the data will never change, so Python uses the same data;
ids are always the same. For mutable objects,
since they can potentially change, [shallow] copy creates a new object.
Deep copy is related to nested structures.
If you have list of lists, then deepcopy copies the nested lists also,
so it is a recursive copy. With just copy, you have a new outer list,
but inner lists are references.
Assignment (=) does not copy. It simply sets the reference to the old data.
So you need copy to create a new list with the same contents.