Reputation: 13
I am newbie in python. There is a problem in changing the value in a 2Xn list. Below is the code I tried:
alist =[[0,0,0]]*10
b=[0]*10
for i in range(10):
alist[i][0]=i
alist[i][2]=2i
b[i]=I
what I expect is:
alist=[[0,0,0],[1,0,2],[2,0,4],...[9,0,18]],
b=[0,1,2,..9]
It turns out that b is as I expected, but alist=[[9,0,18],[9,0,18],[9,0,18],...[9,0,18]]
. all the elements seem to be assigned to the last call.
I am totally confused. Could anyone help? Thanks!
Upvotes: 0
Views: 324
Reputation: 10951
That's because :
alist =[[0,0,0]]*10
is not the same as alist = [[0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0]]
In your assignment you are just creating a list of 10 duplicates of the same item [0,0,0]
, so any change to one of them will be reflected to the remaining 9.
See below demonstration:
>>> x = [0,0,0]
>>> id(x)
140348692006664
>>>
>>>
>>> l1 = [x]*10
>>> l2 = [[0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0]]
>>>
>>>
>>> for i in l1:
print(id(i))
140348692006664
140348692006664
140348692006664
140348692006664
140348692006664
140348692006664
140348692006664
140348692006664
140348692006664
140348692006664
>>>
>>>
>>> for j in l2:
print(id(j))
140348692008712
140348692008648
140348691779528
140348692008520
140345708853320
140348692007688
140348691927176
140348691829640
140348691831112
140345708570760
And secondly, alist
is a list of mutable objects(list) so, any change in any one of them will be reflected to the other due to the nature of your assignment (alist = [[0,0,0]]*10
), whereas blist
is a list of immutable objects(list of integer 0), so when you do blist[i]=i
you are not changing the value but creating a new reference to the new object.
>>> l4 = ['1']*10 #list of immutable objects
>>> l4
['1', '1', '1', '1', '1', '1', '1', '1', '1', '1']
>>>
>>>
>>> l4[0]='0'
>>> l4
['0', '1', '1', '1', '1', '1', '1', '1', '1', '1'] #only first item affected
>>>
>>> l5 = [{1:'1'}]*10 #list of mutable objects
>>>
>>> l5
[{1: '1'}, {1: '1'}, {1: '1'}, {1: '1'}, {1: '1'}, {1: '1'}, {1: '1'}, {1: '1'}, {1: '1'}, {1: '1'}]
>>>
>>> l5[0][1] = 'ONE'
>>>
>>> l5
[{1: 'ONE'}, {1: 'ONE'}, {1: 'ONE'}, {1: 'ONE'}, {1: 'ONE'}, {1: 'ONE'}, {1: 'ONE'}, {1: 'ONE'}, {1: 'ONE'}, {1: 'ONE'}] #all affected
Upvotes: 0
Reputation: 105
You should do:
alist = [[0, 0, 0] for __ in xrange(10)]
or use range(10) for Python3
this is nicely explained in Python-guide
Upvotes: 0
Reputation: 2618
Lists are mutable, so [[0,0,0]] * 10
will give you a list containing ten references to the same list, so a change to any one of them will be a change to all. (Yes, this is a slightly tricksy thing about Python that one needs to get used to!)
There are many ways to generate the list of lists you want. One of them would be to use a simple list comprehension:
alist = [[i, 0, 2 * i] for i in range(10)]
Edit: In case you’re not used to list comprehensions yet, the above is equivalent to:
alist = []
for i in range(10):
alist.append([i, 0, 2 * i])
Upvotes: 1