Python variables are references to objects, so all you're doing is creating 2 references to 1 object. You need to make the second object a copy of the first before you can modify it independently of the first.
second_var = list(base)
General Explanation
Copying mutable objects in python can be tricky. If you don't do it correctly you can end up with weird bugs that are hard to identify.
>>> base = [0, 1, [2.3, 2.5], 3]
>>> # note the nested list at index 2
You can create an alias. Both variables refer to one and the same object. They have the same identity.
>>> alias = base
>>> alias is base
True
You can create a shallow copy. The 2 objects are different objects (don't have the same identity) but any mutable members will be shared between them. I can think of 4 ways to make shallow copies of lists. As far as I know, they are all functionally equivalent.
>>> method_copy = base.copy()
>>> list_copy = list(base)
>>> list_comprehension_copy = [b for b in base]
>>> from copy import copy
>>> shallow_copy = copy(base)
>>> [base is _copy for _copy in [method_copy, list_copy, list_comprehension_copy, shallow_copy]]
[False, False, False, False]
>>> [base[2] is _copy[2] for _copy in [method_copy, list_copy, list_comprehension_copy, shallow_copy]]
[True, True, True, True]
You can create a deep copy. The 2 objects will be different objects, and any mutable members will also be distinct. If you need a truly copy of a nested data structure, you want a 'deep copy'.
>>> from copy import deepcopy
>>> deep_copy = deepcopy(base)
>>> base is deep_copy
False
>>> base[2] is deep_copy[2]
False
Now let's see how they all behave when we try to append to the outer list.
>>> base.append(4)
>>> base
[0, 1, [2.3, 2.5], 3, 4]
>>> alias
[0, 1, [2.3, 2.5], 3, 4]
>>> method_copy
[0, 1, [2.3, 2.5], 3]
>>> list_copy
[0, 1, [2.3, 2.5], 3]
>>> list_comprehension_copy
[0, 1, [2.3, 2.5], 3]
>>> shallow_copy
[0, 1, [2.3, 2.5], 3]
>>> deep_copy
[0, 1, [2.3, 2.5], 3]
See how only alias
updated when we appended onto base
. The rest remained unchanged.
Now let's see what happens when we append to the inner list at index 2.
>>> base[2].append(2.7)
>>> base
[0, 1, [2.3, 2.5, 2.7], 3, 4]
>>> alias
[0, 1, [2.3, 2.5, 2.7], 3, 4]
>>> method_copy
[0, 1, [2.3, 2.5, 2.7], 3]
>>> list_copy
[0, 1, [2.3, 2.5, 2.7], 3]
>>> list_comprehension_copy
[0, 1, [2.3, 2.5, 2.7], 3]
>>> shallow_copy
[0, 1, [2.3, 2.5, 2.7], 3]
>>> deep_copy
[0, 1, [2.3, 2.5], 3]
See how the shallow copies all updated because they all share one-and-the-same list at index 2. Only deep_copy
remained unchanged because it has its own unique copy of that inner list.