Frage

ich lese Wie man wie ein Informatiker denkt Dies ist ein Einführungstext für „Python-Programmierung“.

Ich möchte das Verhalten des Multiplikationsoperators (*), wenn es auf Listen angewendet wird.

Betrachten Sie die Funktion 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

Die tatsächliche Ausgabe ist

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

Die richtige Version von make_matrix Ist :

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

Der Grund, warum die erste Version von make_matrix fails (wie im Buch unter 9.8 erklärt) ist das

...jede Zeile ist ein Alias ​​der anderen Zeilen...

ich wundere mich warum

[[0] * columns] * rows

Ursachen ...jede Zeile ist ein Alias ​​der anderen Zeilen...

aber nicht

[[0] * columns]

d.h.warum jeder [0] in einer Zeile ist kein Alias ​​eines anderen Zeilenelements.

War es hilfreich?

Lösung

ALLES in Python sind Objekte, und Python erstellt niemals Kopien, es sei denn, Sie werden ausdrücklich dazu aufgefordert.

Wenn Sie das tun

innerList = [0] * 10

Sie erstellen eine Liste mit 10 Elementen, alle beziehen sich auf dasselbe int Objekt 0.

Da es sich um ganzzahlige Objekte handelt unveränderlich, wenn Sie das tun

innerList[1] = 15

Sie ändern das zweite Element der Liste, sodass es auf eine andere ganze Zahl verweist 15.Das funktioniert immer, weil int Objekte Unveränderlichkeit.

Deshalb

outerList = innerList * 5

Werde ein erstellen list Objekt mit 5 Elementen, jedes davon ist eine Referenz auf das gleiche innerList genau wie oben.Aber seit list Objekte sind veränderlich:

outerList[2].append('something')

Ist das gleiche wie:

innerList.append('something')

Weil es sich um zwei Verweise auf die handelt Dasselbe list Objekt.Das Element landet also in dieser Single list.Es scheint ein Duplikat zu sein, aber Tatsache ist, dass es nur eines gibt list Objekt und viele Verweise darauf.

Im Gegensatz dazu, wenn Sie es tun

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

Hier sind Sie ja Erstellen ein anderer list Objekt (mit + mit Listen ist eine explizite Kopie) und Zuweisen einer Referenz darauf an der zweiten Position von outerList.Wenn Sie das Element auf diese Weise „anhängen“ (nicht wirklich anhängen, sondern eine andere Liste erstellen), innerList bleibt davon unberührt.

Andere Tipps

Listen sind keine Grundelemente, sie werden als Referenz übergeben.Eine Kopie einer Liste ist ein Zeiger auf eine Liste (im C-Jargon).Alles, was Sie mit der Liste tun, betrifft alle Kopien der Liste und die Kopien ihres Inhalts, es sei denn, Sie erstellen eine flache Kopie.

[[0] * columns] * rows

Hoppla, wir haben gerade eine große Liste mit Verweisen auf [0] erstellt.Wenn Sie einen ändern, ändern Sie alle.

Ganzzahlen werden nicht als Referenz übergeben, sie werden wirklich kopiert, daher erzeugt [0] * content wirklich viele NEUE Nullen und hängt sie an die Liste an.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top