Stretch Matrix

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Stretch Matrix
Hallo,
ich bearbeite gerade Blatt 1 und habe folgenden Code für die Methode stretch_matrix():

def stretch_matrix(s, d):
    matrix = [[0] * d] * d

    n = 0
    for i in matrix:
        i[n] = s
        n += 1
    return np.array(matrix)

Für den Aufruf von beispielsweise stretch_matrix(3,3) würde ich als Ergebnis [[3,0,0],[0,3,0],[0,0,3]] erwarten, tatsächlich bekomme ich als Ergebnis aber [[3,3,3], [3,3,3], [3,3,3]].

Könnte mir jemand erklären, was da genau passiert?

Vielen Dank schonmal


Im Moment, in dem du [x] * 4
schreibt, erhälst du in Python die Liste [m][x, x, x, x][/m]. Dies ist eine Liste mit vier Referenzen auf dasselbe [m]x[/m]. Wird nun dieses [m]x[/m] modifiziert, so passiert das auch bei allen anderen Auftritten von [m]x[/m].
Deine Liste an Listen [m]matrix[/m] besteht also aus [m]d[/m] Auftritten derselben Liste [m][0] * d[/m]. Python evaluiert beim Ausführen diesen Codeteil genau einmal zu Beginn und gibt dann eine Liste wie oben beschrieben zurück.

Aber, wenn ich [m]a = [2] * 6[/m] gefolgt von [m]a[0] = 1[/m] ausführe erhalte ich ja auch [m][1,2,2,2,2,2][/m] und nicht etwa [m][1,1,1,1,1,1][/m]. Das stimmt, hier wird allerdings nicht das Element selbst verändert, sondern bloß auf ein anderes Element gezeigt. Die oben erklärte Magie des Multiplikationsoperators stimmt auch weiterhin.
Interessanterweise kopiert der Operator hier nie irgendwelche Elemente, auch nicht bei immutable Objekten (wie Integer oder ähnliche). Da diese aber immutable sind, kommt es hier selten zu Verwirrungen (obiges Fallbeispiel funktionierte ja nicht, da das Objekt unveränderbar ist).

Vielleicht hilft ja auch das hier: http://pythontutor.com/visualize.html#code=size%20%3D%203 d%20%3D%203 matrix%20%3D%20[[d]%20*%20size]%20*%20size&cumulative=false&curInstr=3&heapPrimitives=false&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=[]&textReferences=false Hier wird effektiv derselbe Code ausgeführt, also die kritische Zeile zumindest, und danach das Pointer-Layout (also wie die Liste genau gespeichert ist) graphisch dargestellt.


Vielen Dank für deine ausführliche Antwort!
Das hat mir sehr weitergeholfen, ich hatte schon an meinem Verstand gezweifelt.