Please ignore secret bonuses. Secret tests do NOT award bonus. Max hw grade is 30+2 bonus efficiency

Do you need help?

Sulla list comprehension (domanda non inerente a HW)

Plush (340 points)
2 4 7
in Programmare in Python by (340 points)
Se genero in memoria due liste:

a = [[4,2,8,6],[1,5,61,3]]

b = [[0,0,0,0],[0,0,0,0]])

poi, eseguo sulla console:

b[0][0] = a[0][0]

allora giustamente ritorna come lista:

b = [[4,0,0,0],[0,0,0,0]]

Tuttavia se la stessa lista b è generata tramite una list comprehension:

b = [[0]*len(a[0])]*len(a)

ed eseguo la stessa operazione di prima:

b[0][0] = a[0][0]

adesso ritorna come lista:

b = [[4,0,0,0],[4,0,0,0]]

Quindi mi chiedo, probabilmente quando una lista è generata sotto forma di list comprehension, allora l'indicizzazione funziona in modo diverso? Non trovo niente a riguardo, se qualcuno sa cosa sta succedendo potrebbe farmi sapere di più?
361 views
closed

1 Answer

Best answer
E
Edward (25950 points)
4 4 172
by (26.0k points)
selected by
Praticamente quando usi * come operatore di ripetizione, quello ripete quell'identico oggetto,

Infatti se provi a fare lista = [[1]]*3 noterai che id(lista[0]) == id(lista[1]).

Qui entrano in gioco gli oggetti mutabili e gli oggetti immutabili.
Quando ripeti un oggetto mutabile, e vai a modificarlo (esempio: lista), siccome l'oggetto è identico per tutte le volte che viene ripetuto, allora ne vengono modificate anche le sue ripetizioni.
Questo non avviene con gli oggetti immutabili. Non potendoli modificare, tu in genere modifichi il contenitore dell'oggetto, e non l'oggetto stesso come avviene con quelli mutabili.

EDIT:

Comunque [[0]*len(a[0])]*len(a) non è una list comprehension.
Una list comprehension è del tipo:

[x**2 for x in lista]
[i for i in range(num)] (esempio stupido perchè basterebbe fare list(range(num)) ma spero di rendere l'idea)
ecc..

Infatti le list comprehension, creano un nuovo oggetto per ogni ciclo del for, quindi non avresti il problema che hai con l'operatore di ripetizione.
Ad esempio se fai:

a = [[4,2,8,6],[1,5,61,3]]
b = [[0 for _ in range(len(a[0]))] for _ in range(len(a))]
b[0][0] = a[0][0]

Noterai che b sarà uguale a [[4,0,0,0],[0,0,0,0]]

In questo caso, siccome andavi a ripetere un intero (che è un oggetto immutabile), avresti potuto usare l'operatore di ripetizione al posto della list comprehension interna e fare:
b = [[0] * len(a[0]) for _ in range(len(a))]
Plush (340 points)
2 4 7
by (340 points)
Ok ho capito, grazie!