I accidently noticed that directly updating elements in a list of lists was working.
There are lots of Q&A about updating a list of lists. Yet all the answers I inspected indicate that
But in the following example I can directly update a list.
All answers I found about the subject are fairly old, so is this later on added to python?
# COMPREHENSION ==================================
li = [
["spam1", "eggs1"],
["spam2", "eggs2"]
]
print("\nCOMPREHENSION ---------------")
print("INPUT", li)
li = [["new", l[1]] for l in li]
print("OUTPUT", li)
# INDEX ===========================================
li = [
["spam1", "eggs1"],
["spam2", "eggs2"]
]
print("\nINDEX -----------------")
print("INPUT", li)
for index, l in enumerate(li):
li[index] = ["new", l[1]]
print("OUTPUT", li)
# IN PLACE ========================================
li = [
["spam1", "eggs1"],
["spam2", "eggs2"]
]
print("\nIN PLACE --------------")
print("INPUT", li, " <<<<<<<<<<<<<")
for i in li:
i[0] = f'new'
print("OUTPUT", li, " <<<<<<<<<<<<<")
Result
COMPREHENSION ---------------
INPUT [['spam1', 'eggs1'], ['spam2', 'eggs2']]
OUTPUT [['new', 'eggs1'], ['new', 'eggs2']]
INDEX -----------------
INPUT [['spam1', 'eggs1'], ['spam2', 'eggs2']]
OUTPUT [['new', 'eggs1'], ['new', 'eggs2']]
IN PLACE --------------
INPUT [['spam1', 'eggs1'], ['spam2', 'eggs2']] <<<<<<<<<<<<<
OUTPUT [['new', 'eggs1'], ['new', 'eggs2']] <<<<<<<<<<<<<
Everything actually works as expected. You are right, that inside iteration element is just copied, so changing the copied element does not change actual list. See example:
In [1]: x = [1,2,3,4,5,6,7,8]
In [2]: for a in x:
...: if a ==2:
...: a=3
In [3]: x
Out[3]: [1, 2, 3, 4, 5, 6, 7, 8]
What happens, when an element of list is actually a list?
In [4]: z = [[1,2],[3,4],[5,6]]
In [5]: for a in z:
...: if a[0] ==3:
...: a = [7,8]
In [6]: z
Out[6]: [[1, 2], [3, 4], [5, 6]]
You have a copy of an inner list assigned to a
, so assigning to a
another list does not change outer list z
.
However what is actually copied inside iteration is not an inner list, but a reference to it. So a
points to inner list itself, not its copy. You can actually modify this inner list elements. Like here:
In [8]: for a in z:
...: if a[0] ==3:
...: a[0] = 7
In [9]: z
Out[9]: [[1, 2], [7, 4], [5, 6]]
Or even add/remove elements from it:
In [10]: for a in z:
...: if a[0] ==1:
...: a.append(22)
In [10]: z
Out[10]: [[1, 2, 22], [7, 4], [5, 6]]