list.append() - eigenartiges Verhalten

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Fel
User
Beiträge: 1
Registriert: Mittwoch 23. Oktober 2019, 10:42

Hallo,
ich möchte alle Kombinationen aus 0 und 1 in einer 2x2 list generieren und habe dazu schnell ein paar Zeilen in Python 2.7 geschrieben:

Code: Alles auswählen

kombi = [[0,0],[0,0]]
kombinationen = []

for i in range(2):
    kombi[0][0] = i
    for j in range(2):
        kombi[0][1] = j
        for k in range(2):
            kombi[1][1] = k
            for l in range(2):
                kombi[1][0] = l
                print kombi
                kombinationen.append(kombi)
print 'Kombinationen:', kombinationen
Interessanterweise ist das hier der Output:

Code: Alles auswählen

[[0, 0], [0, 0]]
[[0, 0], [1, 0]]
[[0, 0], [0, 1]]
[[0, 0], [1, 1]]
[[0, 1], [0, 0]]
[[0, 1], [1, 0]]
[[0, 1], [0, 1]]
[[0, 1], [1, 1]]
[[1, 0], [0, 0]]
[[1, 0], [1, 0]]
[[1, 0], [0, 1]]
[[1, 0], [1, 1]]
[[1, 1], [0, 0]]
[[1, 1], [1, 0]]
[[1, 1], [0, 1]]
[[1, 1], [1, 1]]
Kombinationen: [[[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]]]
Warum sind alle Einträge der Liste 1??
Ich habe erstmal angenommen, dass es ein Deep-Copy Problem ist und habe stattdessen die Zeile

Code: Alles auswählen

kombinationen.append(kombi[:])
verwendet. Aber das löst das Problem ebenfalls nicht.
Wenn jemand eine Idee hat, wäre ich dankbar :)

Liebe Grüße,
Fel
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da du immer die gleiche Liste modifizierst, ist das kein Wunder. Und nicht nur das: kombi ist eine Liste, aber auch seine Eintraege sind Listen. Und *DIE* bleiben auch bei kombi[:] unveraendert.

Ganz generell macht man sowas so nicht. Man modifiziert keine bestehenden Datenstrukturen, die man dann eh kopieren muss. Man erzeugt einfach immer neue.

Gibt es einen Grund, warum du nicht einfach itertools.product benutzt?
Benutzeravatar
__blackjack__
User
Beiträge: 13925
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Fel: Python 2 sollte man nicht mehr verwenden. Insbesondere für neuen Code.

Mit dem angesprochenen `itertools.product()` könnte eine Lösung so aussehen:

Code: Alles auswählen

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


def main():
    bit_count = 4
    bits_per_row = bit_count // 2
    table = list()
    for bits in product([0, 1], repeat=bit_count):
        table.append([bits[:bits_per_row], bits[bits_per_row:]])
    pprint(table)


if __name__ == "__main__":
    main()]
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
Antworten