c.append(b[j])
adds into c
a reference to the object b[j]
.
Thereafter, changing c[j]
changes b[j]
.
To avoid this, produce a copy, of b[j]
, instead:
c.append(copy.copy(b[j]))
That requires import copy
.
Indeed, Python tends to use references instead of copying elements, with certain exceptions (e.g., dict .copy
, slicing, sorted()
, dict .get()
produce shallow copies). Would you write d=b
, they would point to the same list (of lists). More: Which commands/methods return a deepcopy / shallowcopy / original?
Would b[j]
be a nested list instead of a list (e.g., [[1,2,3],[4,5,6]]
), its elements would be pointers (references) to the lists on the next level (to the lists [1,2,3]
and [4,5,6]
). Then copy.copy(b[j])
would produce a copy (c[j]
) of that list of pointers. Changing c[j]
would then not affect b
but changing c[j][k]
before that would affect b[j][k]
.
Using copy.deepcopy
instead of copy.copy
always makes the result fully independent, as it recursively copies everything (also the nested lists).
As Storyteller wrote, also b
depends on a
unless you sort a copy of a
instead of a
:
b = sorted(copy.deepcopy(a), lambda a : a[1])
.
Indeed, sorted()
produces a shallow copy, so the second level is not copied but pointed to. For non-nested lists, shallow copy is enough for independence.