Listenproblem

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Luroka
User
Beiträge: 2
Registriert: Montag 5. September 2022, 10:57

Hallo,
ich experimentiere gerade ein bisschen mit Listen in Python und bin auf ein Problem gestoßen das ich nicht ganz verstehe. Der Code unten gibt für jedes Listenelement den Wert 6 aus, obwohl es eigentlich (nach meinem Gedankengang), 2 sein müsste. Schließlich wird durch die erste Schleife genau zwei mal auf jedes Listenelement zugegriffen und somit auch nur zwei mal, eins addiert. Übersehe ich da etwas oder warum ist das so?

Danke schon mal für die Antworten :)

Code: Alles auswählen

List = []
yList = []

for x in range(3):
    yList.append([0,0,0])
for y in range(3):
    List.append(yList)

for i in range(2):
    for x in range(3):
        for y in range(3):
            for z in range(3):
                List[x][y][z] += 1

print(List)
#Ausgabe: [[[6, 6, 6], [6, 6, 6], [6, 6, 6]], [[6, 6, 6], [6, 6, 6], [6, 6, 6]], [[6, 6, 6], [6, 6, 6], [6, 6, 6]]]
Benutzeravatar
__blackjack__
User
Beiträge: 14077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Luroka: Du hast da im inneren nicht 3 verschiedene Listen sondern 3 mal die *selbe* Liste. `yList` ist *eine* Liste die 3 mal an `List` angehängt wird. Python kopiert bei einfachen Zuweisungen und Argumenten nie von sich aus Werte, sondern übergibt das Objekt. Egal über welchen Index Du darauf zugreifst, es ist immer die selbe Liste und die Änderung sieht man dann natürlich auch wenn man über einen anderen Index darauf zugreift, oder eben alles ausgeben lässt.

Simpleres Beispiel:

Code: Alles auswählen

In [65]: A = [42]

In [66]: B = []

In [67]: B.append(A)

In [68]: B.append(A)

In [69]: B
Out[69]: [[42], [42]]

In [70]: B[0] is B[1]
Out[70]: True

In [71]: B[0][0] += 1

In [72]: B
Out[72]: [[43], [43]]

In [73]: B[1].append(23)

In [74]: B
Out[75]: [[43, 23], [43, 23]]

In [75]: A
Out[75]: [43, 23]
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Luroka
User
Beiträge: 2
Registriert: Montag 5. September 2022, 10:57

@__blackjack__ Danke für die Antwort, jetzt ergibt es für mich auch Sinn.
Benutzeravatar
__blackjack__
User
Beiträge: 14077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Noch Anmerkungen zum Quelltext: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassennamen (PascalCase).

Grunddatentypen haben in Namen nichts zu suchen. Den Typ ändert man öfter mal während der Programmentwicklung und dann hat man entweder falsche, irreführende Namen oder muss durch das Programm gehen und alle betroffenen Namen anpassen.

Wenn man einen Namen aus syntaktischen Gründen braucht, den Wert aber nicht, dann ist der konventionelle Name `_`, damit der Leser weiss, dass das kein Fehler ist, oder der Code noch unfertig ist.

Man würde zum erstellen der verschachtelten Liste eher eine „list comprehension“ schreiben. Das ist kürzer und dem Leser wird leichter klar wie die endgültige Struktur aussieht.

Indexzugriffe sind in Python oft ein „anti pattern“ weil man direkt über die Elemente von Sequenzen wie Listen iterieren kann, ohne den unnötigen Umweg über einen Laufindex. Der wird hier nur für die innerste Schleife benötigt. Und dort würde ich die 3 nicht hart kodieren, sondern mich an der tatsächlichen Länge der innersten Listen orientieren.

Code: Alles auswählen

#!/usr/bin/env python3
from pprint import pprint


def main():
    nested_structure = [[[0] * 3 for _ in range(3)] for _ in range(3)]

    for _ in range(2):
        for outer in nested_structure:
            for inner in outer:
                for i in range(len(inner)):
                    inner[i] += 1

    pprint(nested_structure)


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten