Appending the same list to another one [duplicate] - python

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 6 years ago.
I have to append the same list to another one more than one time, and then modify only one of them.
I tried
list_a = []
list_b = [0,0,0]
for x in range(3):
list_a.append(list_b)
but the problem is that if I try
list_a[0][0] = 1
it modifies list_a[1][0] and list_a[2][0] also.
How can I avoid that?

Better way to create a list like this if all you want is to create empty list with all 0s is:
my_list = [[0]*3 for _ in range(3)]
Let's verify the result whether it has the same issue or not:
>>> my_list
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> my_list[0][0] = 1
>>> my_list
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]
# ^ ^ ^
# Yipee! value changed only once
For knowing the reason why your code is not working, check: Python list of lists, changes reflected across sublists unexpectedly

Use the following:
list_a = []
list_b = [0,0,0]
for x in range(3):
list_a.append(list_b[:])

You are appending list_b three times, so what you are modifying is the actual list_b object. What you want to do is to make a shallow copy, this be done like this
list_a.append(list(list_b))
or like this
list_a.append(list_b[:])

Related

Unexpected behaviour of python matrix (list of lists), assignment is changing whole column [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 4 months ago.
please help me with a question, cause Im getting mad.
I'm creating a 0-matrix, than tried to changed it's first element value to one, but it changes the whole column instead, and I don't get why:
def id_mtrx(n):
m = [[0]*n]*n
m[0][0]=1
return m
here is output:
[[1, 0], [1, 0]]
while I was expecting:
[[1, 0], [0, 0]]
It looks very simple, what can be wrong?
You are creating multiple references to the same list object instead of creating new list, try:
n = 2
m = [[0 for _ in range(0, n)] for _ in range (0, n)]
m[0][0] = 1
print(m)
output is:
[[1, 0], [0, 0]]

autofilling python list of lists [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 5 years ago.
When I create and fill a list of lists some odd behaviour pops up:
list1 = [[0,0,0],[0,0,0],[0,0,0]]
list2 = [[0]*3]*3
print('lists still look equal here:')
print(list1)
print(list2)
list1[1].pop(1)
list2[1].pop(1)
print('but not anymore:')
print(list1)
print(list2)
gives me this output:
lists look completely equal here:
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
but not anymore:
[[0, 0, 0], [0, 0], [0, 0, 0]]
[[0, 0], [0, 0], [0, 0]]
So the second list 'pops' from every little list instead of just the one I'm trying to. I wonder what causes this behaviour and if there is a more elegant way to fill indexable lists if I need a large amount of long lists instead of just these tiny ones?
When using the operator * it means the items are pointing to the same memory location.
Therefore when poping from the first list only the first item is removed.
And when poping from the second list, as each of the elements in the list pointing to the same memory location, all elements get affected.
Take a look at this:
list1 = [[0,0,0],[0,0,0],[0,0,0]]
list2 = [[0]*3]*3
for elem in list1:
print (id(elem))
print ('--------')
for elem in list2:
print (id(elem))
Output:
32969912
32937024
32970192
--------
32970752
32970752
32970752
As you can see, each element in the second list has the same id.
This is quite a common mistake. In the second definition:
list2 = [[0] * 3]*3
the three sub-lists share the same reference in memory, so if you pop from one, you pop from "all" of them, because all three of them point to the same object.
To avoid this, use:
list2 = [[0] * 3 for _ in range(3)]
which will generate different three lists.

Editing List of list of list in Python [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Changing an element in one list changes multiple lists [duplicate]
(4 answers)
Closed 6 years ago.
I am trying to edit elements in my list of list of list but it is editing multiple elements.
L1 = [[0,0] for count in range(2)]
L2 = [L1 for count in range(2)]
L2[0][0][0] = 5
print(L2)
What I expect is [[[5, 0], [0, 0]], [[0, 0], [0, 0]]]
But what I get is [[[5, 0], [0, 0]], [[5, 0], [0, 0]]]
It seems that I am editing the original list. Can someone explain how to edit a single element or set up nested lists where this effect won't occur.
Many thanks
Don't reuse the variable:
L2 = [[[0,0] for count in range(2)] for count in range(2)]
Then the inner part [[0,0] for count in range(2)] will get recreated every time as a fresh, separate list.

why can't I change only a single element in a nested list in Python [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 4 years ago.
I just met something really strange of Python:
>>> out=[[0]*3]*3
>>> out
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> out[0][1]
0
>>> out[0][1]=9
>>> out
[[0, 9, 0], [0, 9, 0], [0, 9, 0]]
well, obviously, what I want is :
[[0, 9, 0], [0, 0, 0], [0, 0, 0]]
isn't strange? I'm not very familiar with Python, but Python always impresses me with its intuitive behavior. But how it comes up with this?
... and how can I get what I need?
thanks!
Watt
A strange behaviour indeed, but that's only because * operator makes shallow copies, in your case - shallow copies of [0, 0, 0] list. You can use the id() function to make sure that these internal lists are actually the same:
out=[[0]*3]*3
id(out[0])
>>> 140503648365240
id(out[1])
>>> 140503648365240
id(out[2])
>>> 140503648365240
Comprehensions can be used to create different lists as follows:
out = [ [0]*3 for _ in range(3) ]
Using * to duplicate elements in lists is a shallow copy operation, so you will end up with multiple references to the same mutable objects if you use this on a list that contains mutable objects.
Instead, use the following to initialize your nested list:
out = [[0]*3 for _ in range(3)]
You can see that with your method, each entry in out is actually a reference to the same list, which is why you see the behavior that you do:
>>> out = [[0]*3]*3
>>> out[0] is out[1] is out[2]
True

Python list problem [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 5 years ago.
python:
m=[[0]*3]*2
for i in range(3):
m[0][i]=1
print m
I expect that this code should print
[[1, 1, 1], [0, 0, 0]]
but it prints
[[1, 1, 1], [1, 1, 1]]
This is by design. When you use multiplication on elements of a list, you are reproducing the references.
See the section "List creation shortcuts" on the Python Programming/Lists wikibook which goes into detail on the issues with list references to mutable objects.
Their recommended workaround is a list comprehension:
>>> s = [[0]*3 for i in range(2)]
>>> s
[[0, 0, 0], [0, 0, 0]]
>>> s[0][1] = 1
>>> s
[[0, 1, 0], [0, 0, 0]]
This is a bit devilish, but quite obvious when you understand what you're doing. when you're doing the [[0]*3]*2 bit, you're first creating a list with 3 zeros, then you copy that to make two elements. But when you do that copy, you do not create new lists with the same contents, but rather reference the same list several times. So when you change one, they all change.
An example to highlight it:
In [49]: s = [[]]*2 # Create two empty lists
In [50]: s # See:
Out[50]: [[], []]
In [51]: s[0].append(2) # Alter the first element (or so we think)
In [52]: s # OH MY, they both changed! (because they're the same list!)
Out[52]: [[2], [2]]

Categories