2016-04-12 4 views
0

Я новичок в python. Существует проблема с изменением значения в списке 2Xn. Ниже приведен код, который я попробовал:изменить значение в списке Python

alist =[[0,0,0]]*10 
b=[0]*10 

for i in range(10): 
    alist[i][0]=i 
    alist[i][2]=2i 
    b[i]=I 

, что я ожидаю:

alist=[[0,0,0],[1,0,2],[2,0,4],...[9,0,18]], 
b=[0,1,2,..9] 

Оказывается, что б как я ожидал, но alist=[[9,0,18],[9,0,18],[9,0,18],...[9,0,18]]. все элементы, как представляется, привязаны к последнему вызову. Я полностью смущен. Может ли кто-нибудь помочь? Благодаря!

+0

Это, вероятно, то же самое [в этом вопросе] (http://stackoverflow.com/questions/240178/python-list-of-lists-changes-reflected-across- sublists-неожиданно) – syntonym

ответ

0

Это потому, что:

alist =[[0,0,0]]*10 не то же самое, как 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]]

В вашем задании вы просто создаете список из 10 дублей одного и того же элемента [0,0,0], так что любое изменение одного из них будут отражены к оставшемуся 9.

ниже демонстрации:

>>> 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 

Во-вторых, alist - это список изменяемых объектов (список), поэтому любое изменение в любом из них будет отражено в другом из-за характера вашего назначения (alist = [[0,0,0]]*10), тогда как blist - это список неизменяемых объектов (список от целого числа 0), поэтому, когда вы делаете blist[i]=i, вы не меняете значение, а создаете новую ссылку на новый объект.

>>> 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 
+0

Большое спасибо. кристально чистый! – Dong

+0

@Dong .. с удовольствием .. :) –

0

Списки изменчивы, поэтому [[0,0,0]] * 10 даст вам список, содержащий десять ссылок на тот же список , поэтому изменение любого из них будет изменить все. (Да, это немного сложная вещь о Python, к которой нужно привыкнуть!)

Существует множество способов генерации списка нужных вам списков. Один из них должен был бы использовать простой список понимание:

alist = [[i, 0, 2 * i] for i in range(10)] 

Edit: В случае, если вы не привыкли к списковых все же, выше эквивалентно:

alist = [] 
for i in range(10): 
    alist.append([i, 0, 2 * i]) 
+0

Большое спасибо. Это кристально чистое – Dong

0

Вы должны сделать:

alist = [[0, 0, 0] for __ in xrange(10)] 

или использование диапазона (10) для Python3

это хорошо объяснено в Python-guide

Смежные вопросы