2012-06-27 15 views
6

Qui è un programma molto semplice:Python: come aggiungere nuovi elementi in un elenco di elenchi?

a = [[]]*3 

print str(a) 

a[0].append(1) 
a[1].append(2) 
a[2].append(3) 

print str(a[0]) 
print str(a[1]) 
print str(a[2]) 

Ecco l'output che mi aspettavo:

[[], [], []] 
[1] 
[2] 
[3] 

Ma invece ottengo questo:

[[], [], []] 
[1, 2, 3] 
[1, 2, 3] 
[1, 2, 3] 

C'è davvero qualcosa che faccio non arrivare qui!

+0

Si deve usare un elenco di _lists_ invece di un elenco di (lo stesso) lista come le deduce titolo. –

risposta

12

Si deve fare

a = [[] for i in xrange(3)] 

non

a = [[]]*3 

Ora funziona:

$ cat /tmp/3.py 
a = [[] for i in xrange(3)] 

print str(a) 

a[0].append(1) 
a[1].append(2) 
a[2].append(3) 

print str(a[0]) 
print str(a[1]) 
print str(a[2]) 

$ python /tmp/3.py 
[[], [], []] 
[1] 
[2] 
[3] 

Quando fai qualcosa come a = [[]]*3 si ottiene la stessa lista [] tre volte in un elenco . Lo stesso significa che quando si cambia uno di essi si cambiano tutti (perché c'è una sola lista a cui si fa riferimento per tre volte).

È necessario creare tre elenchi indipendenti per aggirare questo problema. E lo fai con una lista di comprensione. Costruisci qui un elenco costituito da liste vuote indipendenti []. La nuova lista vuota verrà creata per ogni iterazione su range e xrange non è così importante in questo caso, ma xrange è un po 'meglio perché non produce l'elenco completo dei numeri e restituisce invece un oggetto iteratore).

+2

Sarebbe meglio w/spiegare e usare 'xrange' – okm

+1

@okmò a meno che non sia python 3x :) – Trufa

5

quando si scrive:

a = [[]]*3 

non si farà 3 copie della lista vuota interna, ma invece si fanno 3 riferimenti allo stesso oggetto.

Allo stesso modo, se si fa:

b = [1,2,3] 
c = b 
c.append(4) 
print b 

Si ottiene come output:

[1, 2, 3, 4] 

Questo è dovuto al fatto B e C sono due riferimenti diversi (si può dire due nomi diversi) alla stessa lista. Puoi cambiare l'oggetto da qualsiasi riferimento, ma vedrai i risultati da tutti loro, poiché indicano la stessa cosa.

5

Il problema fondamentale del vostro approccio è che quando si moltiplica la lista per tre, l'elenco risultante contiene tre della stessa lista. Quindi, a[0], a[1] e a[2] fanno riferimento tutti allo stesso modo. Quando si aggiunge a uno di questi, si aggiunge alla stessa lista. Questo è il motivo per cui l'effetto delle tue chiamate append() sembra essere triplicato.

Invece, genera il tuo elenco di liste senza fare riferimento alla stessa lista. Ad esempio, puoi usare la comprensione delle liste, in questo modo.

[[] for i in range(3)] 
1

C'è davvero qualcosa che non capisco qui!

a = [[]]*3 il problema qui è che si impostano gli elenchi per essere lo stesso riferimento, poiché gli array e i dizionari sono memorizzati come riferimenti.

>>> a = [[]]*3 
>>> a[0] is a[1] or a[0] is a[2] 
True 
>>> a[0] is a[1] or a[0] is a[2] or a[1] is a[2] 
True 
>>> 

la stessa cosa si verifica se si fa un = [{}] * 3`

in quanto tale, si deve fare attenzione, si può fare sia un elenco di comprensione [[] for _ in xrange(3)] o staticamente definiscono tutti e 3 gli array [[], [], []].

>>> a = [[] for _ in xrange(3)] 
>>> a[0] is a[1] or a[0] is a[2] or a[1] is a[2] 
False 
>>> 
2

questo vi darà una chiara idea, in l tutti gli oggetti hanno lo stesso ID() e tutti sono mutevoli così la modifica di uno di essi redigerà automaticamente altri troppo, in quanto tutti sono solo refernces ad uno stesso oggetto con id = 18671936 e in m tutti hanno id differente(), quindi tutti sono oggetti diversi.

>>> l = [[]]*4 
>>> for x in l: 
     print(id(x)) 

18671936 
18671936 
18671936 
18671936 

>>> m=[[],[],[],[]] 
>>> for x in m: 
     print(id(x)) 

10022256 
18671256 
18672496 
18631696 

Quindi, è necessario creare la vostra lista in questo modo:

>>> a=[[] for _ in range(4)] 
>>> a[0].append(1) 
>>> a[2].append(5) 
>>> a 
[[1], [], [5], []] 
Problemi correlati