I'm practicing my progamming skills by solving problems from project euler at the moment, and now I've come across some (in my opinion) strange behavior on Python.
When I do:
list = [[1]]*20
I get a list of 20 lists containing element 1, as expected. However, when I would like to append a 2 to the third element from this list, I would do that as follows:
list[3].append(2)
This however changes ALL the elements in the list. Even when I take a detour, like:
l = list[3]
l.append(2)
list[3] = l
All my elements get changed. Can anyone please tell me how to do this and get an output like so:
[[1], [1], [1], [1, 2], [1] .... [1]]
Thanks in advance.
💡 Tips: When you use . append() the original list is modified. The method does not create a copy of the list – it mutates the original list in memory.
append() adds a list inside of a list. Lists are objects, and when you use . append() to add another list into a list, the new items will be added as a single object (item).
Use the multiplication operator to create a list with the same value repeated N times in Python, e.g. my_list = ['abc'] * 3 . The result of the expression will be a new list that contains the specified value N times.
Python lists are mutable objects, so when you do [[1]]*20
it creates one list object [1]
and then places 20 references to it in the toplevel list.
As far as the mutability problem is concerned, this is the same as the following
a = [1,2,3]
b = a
b.append(4)
a # [1,2,3,4]
This happens because b=a
merely copies the reference to the list instance from a
to b
. They are both referring to the same actual list.
In order to create a list of lists, like you tried above, you need to create a unique list for each entry. A list comprehension works nicely:
mainlist = [[1] for x in range(20)]
mainlist[0].append(2)
mainlist # [[1,2],[1],[1],...]
Edit
As an aside, since type names are metaclasses in Python, naming your variables by the type name is a bad idea. The reason is that can cause several issues further down in the code:
a = range(3) # [0,1,2]
type(a) # (type 'list')
isinstance(a, list) # True
Now, create a variable named list
list = range(3)
list # [0,1,2]
isinstance(list, list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
Not to mention, now you cant use the list()
operator
c = list((1,2,3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With