Domanda

Come pensare come un informatico che è un testo introduttivo per "programmazione Python" .

Ci tengo a precisare il comportamento dell'operatore si moltiplicano (*), quando applicato alle liste.

Si consideri la funzione make_matrix

def make_matrix(rows, columns):
"""
  >>> make_matrix(4, 2)
  [[0, 0], [0, 0], [0, 0], [0, 0]]
  >>> m = make_matrix(4, 2)
  >>> m[1][1] = 7
  >>> m
  [[0, 0], [0, 7], [0, 0], [0, 0]]
"""
return [[0] * columns] * rows

L'uscita effettiva è

[[0, 7], [0, 7], [0, 7], [0, 7]]

La versione corretta di make_matrix è:

def make_matrix(rows, columns):
"""
  >>> make_matrix(3, 5)
  [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
  >>> make_matrix(4, 2)
  [[0, 0], [0, 0], [0, 0], [0, 0]]
  >>> m = make_matrix(4, 2)
  >>> m[1][1] = 7
  >>> m
  [[0, 0], [0, 7], [0, 0], [0, 0]]
"""
matrix = []
for row in range(rows):
    matrix += [[0] * columns]
return matrix

Il motivo per cui prima versione di make_matrix non riesce (come spiegato nel libro al 9,8) è che

... ogni riga è un alias delle altre righe ...

Mi chiedo perché

[[0] * columns] * rows

cause ... ogni riga è un alias delle altre righe ...

, ma non

[[0] * columns]

vale a dire. perché ogni [0] fila non è un alias di altro elemento fila.

È stato utile?

Soluzione

tutto in Python sono oggetti, e pitone non fa mai copie a meno che non esplicitamente chiesto di farlo.

Quando si esegue

innerList = [0] * 10

si crea una lista con 10 elementi, tutti loro riferendosi allo stesso oggetto int 0 .

Dato che gli oggetti interi sono immutabile , quando si esegue

innerList[1] = 15

Si sta modificando il secondo elemento della lista in modo che si riferisce ad un altro intero 15 . Che funziona sempre a causa di int oggetti immutabilità.

Ecco perché

outerList = innerList * 5

creerà un oggetto list con 5 elementi, ognuno è un riferimento a stesso innerList come sopra. Ma dal momento che gli oggetti list sono mutevole :

outerList[2].append('something')

è lo stesso:

innerList.append('something')

Perché sono due riferimenti al stesso oggetto list . Così l'elemento finisce in quel singolo list. Sembra essere duplicato, ma il fatto è che c'è un solo oggetto list, e molti riferimenti ad esso.

Al contrario se si fa

outerList[1] = outerList[1] + ['something']

Qui si sono Creazione di altro oggetto list (usando + con gli elenchi è una copia esplicito), e l'assegnazione di un riferimento ad esso nella seconda posizione di outerList. Se "aggiungere" l'elemento in questo modo (in realtà non aggiungendo, ma la creazione di un altro elenco), innerList sarà inalterato.

Altri suggerimenti

elenchi non sono primitivi, vengono passati per riferimento. Una copia di una lista è un puntatore a un elenco (in gergo C). Tutto ciò che fate alla lista accade a tutte le copie della lista e le copie del suo contenuto a meno che non si fa una copia.

[[0] * columns] * rows

Ops, abbiamo appena fatto una grande lista di puntatori a [0]. Modificare uno e li tutti i cambiamenti.

I numeri interi non sono passati per riferimento, sono veramente copiati, quindi [0] * Contenuti sta davvero facendo un sacco di nuovi 0 e aggiungendole alla lista.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top