Why Does Appending to One List Also Append to All Other Lists in My List of Lists

Why does appending to one list also append to all other lists in my list of lists?

[[]]*2 is a list of two references to the same list. You are appending to it and then seeing it twice.

Why does foo.append(bar) affect all elements in a list of lists?

It is because the list contains references to objects. Your list doesn't contain [[1 2 3] [1 2 3]], it is [<reference to b> <reference to b>].

When you change the object (by appending something to b), you are changing the object itself, not the list that contains the object.

To get the effect you desire, your list a must contain copies of b rather than references to b. To copy a list you can use the range [:]. For example:

>>> a = []
>>> b = [1]
>>> a.append(b[:])
>>> a.append(b[:])
>>> a[0].append(2)
>>> a[1].append(3)
>>> print a
[[1, 2], [1, 3]]

Appending to one list in a list of lists appends to all other lists, too

Python lists are mutable objects and here:

plot_data = [[]] * len(positions) 

you are repeating the same list len(positions) times.

>>> plot_data = [[]] * 3
>>> plot_data
[[], [], []]
>>> plot_data[0].append(1)
>>> plot_data
[[1], [1], [1]]
>>>

Each list in your list is a reference to the same object. You modify one, you see the modification in all of them.

If you want different lists, you can do this way:

plot_data = [[] for _ in positions]

for example:

>>> pd = [[] for _ in range(3)]
>>> pd
[[], [], []]
>>> pd[0].append(1)
>>> pd
[[1], [], []]

Appending an integer and a list to a list of lists as a single list

This is one simple way to do it, as long as the number of lists and integers you are planning to append is not large,

a = 4
b = [3,1]
b2 = [5,6,7]
b3 = [2]

b.insert(0,a)
c = []

c.append([x for x in b])
c[0] += b2
c[0] += b3

print(c)

Here I extended your example to cover two additional list. The code should print:

[[4, 3, 1, 5, 6, 7, 2]]

Basically, you prepend the integer to the first list, b. Then you use a list comprehension to create a sublist out of the new b in c. Finally, you simply concatenate all the other lists to it with +=. c[0] is the location of the inner - target list.

This method is not very efficient, and is pretty "manual", but again, it seems suitable for small number of lists with not too many elements.

Appending a list of lists to a list, and clearing the original list of lists

If you'll use the ' list_of_lists.clear() ' at the end of your script it wont be empty and you can reuse it.

For example :

list_1 = [1,2]
list_2 = [3,4,765]
list_3 = [0.3,-2.32]

list_of_lists = [list_1 , list_2 , list_3]

list_of_list_of_lists = [list_of_lists.copy()]

print(list_of_list_of_lists)
# or do whatever you need to do

list_of_lists.clear()

list_of_list_of_lists.append('just_test')

print(list_of_list_of_lists)

The output will be :

[[[1, 2], [3, 4, 765], [0.3, -2.32]]]
[[[1, 2], [3, 4, 765], [0.3, -2.32]], 'just_test']

Python - Appending value to each sublist in list of lists

The problem is you should be appending the str(1) to i, not sub_output:

for i in data:
sub_output.append(i + [sub1])
# sub_output.extend(sub1) <-- you don't need this line.

Note we didn't i.append(sub1) because append() method returns None. You want the full list of i + the single-item list of sub1 appended to your sub_output.

List of lists changes reflected across sublists unexpectedly

When you write [x]*3 you get, essentially, the list [x, x, x]. That is, a list with 3 references to the same x. When you then modify this single x it is visible via all three references to it:

x = [1] * 4
xs = [x] * 3
print(f"id(x): {id(x)}")
# id(x): 140560897920048
print(
f"id(xs[0]): {id(xs[0])}\n"
f"id(xs[1]): {id(xs[1])}\n"
f"id(xs[2]): {id(xs[2])}"
)
# id(xs[0]): 140560897920048
# id(xs[1]): 140560897920048
# id(xs[2]): 140560897920048

x[0] = 42
print(f"x: {x}")
# x: [42, 1, 1, 1]
print(f"xs: {xs}")
# xs: [[42, 1, 1, 1], [42, 1, 1, 1], [42, 1, 1, 1]]

To fix it, you need to make sure that you create a new list at each position. One way to do it is

[[1]*4 for _ in range(3)]

which will reevaluate [1]*4 each time instead of evaluating it once and making 3 references to 1 list.


You might wonder why * can't make independent objects the way the list comprehension does. That's because the multiplication operator * operates on objects, without seeing expressions. When you use * to multiply [[1] * 4] by 3, * only sees the 1-element list [[1] * 4] evaluates to, not the [[1] * 4 expression text. * has no idea how to make copies of that element, no idea how to reevaluate [[1] * 4], and no idea you even want copies, and in general, there might not even be a way to copy the element.

The only option * has is to make new references to the existing sublist instead of trying to make new sublists. Anything else would be inconsistent or require major redesigning of fundamental language design decisions.

In contrast, a list comprehension reevaluates the element expression on every iteration. [[1] * 4 for n in range(3)] reevaluates [1] * 4 every time for the same reason [x**2 for x in range(3)] reevaluates x**2 every time. Every evaluation of [1] * 4 generates a new list, so the list comprehension does what you wanted.

Incidentally, [1] * 4 also doesn't copy the elements of [1], but that doesn't matter, since integers are immutable. You can't do something like 1.value = 2 and turn a 1 into a 2.

Take the content of a list and append it to another list

You probably want

list2.extend(list1)

instead of

list2.append(list1)

Here's the difference:

>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> c = [7, 8, 9]
>>> b.append(a)
>>> b
[4, 5, 6, [1, 2, 3]]
>>> c.extend(a)
>>> c
[7, 8, 9, 1, 2, 3]

Since list.extend() accepts an arbitrary iterable, you can also replace

for line in mylog:
list1.append(line)

by

list1.extend(mylog)


Related Topics



Leave a reply



Submit