mehrdimensionale Arrays

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
antimicro
User
Beiträge: 151
Registriert: Sonntag 29. Februar 2004, 16:24

Hi,
ist jemanden schon mal das hier aufgefallen?

Code: Alles auswählen

B = [[0]*2]*2
A = [[0,0],[0,0]]

print A==B

A[0][1] = 1
B[0][1] = 1

print A==B
Warum sind die beiden Arrays nicht gleich?

Schöne Grüße
Sebastian
greetings
sebi
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Weil sie nicht die selben Daten enthalten.

Code: Alles auswählen

In [6]: A
Out[6]: [[0, 1], [0, 0]]

In [7]: B
Out[7]: [[0, 1], [0, 1]]
Siehe http://www.python-forum.de/topic-17228.html
antimicro
User
Beiträge: 151
Registriert: Sonntag 29. Februar 2004, 16:24

Hi,
ja okay, sollten sie doch aber, oder? Ich hab doch auf beiden die gleiche Operation durchgeführt, oder nicht...
greetings
sebi
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Weil gerade Weihnachten war, hier eine "Grafik" ;)

Code: Alles auswählen

               +---+
            .->| --------.    
     +----+ |  +---+     |                   +---+
A =  |  ----'  | -------.|                .->| --------.
     +----+    +---+    vv         +----+ || +---+     |
     |  ----.            0    B =  |  ----'| | -------.|
     +----+ |  +---+    ^^         +----+  | +---+    vv
            `->| -------'|         |  -----'           0
               +---+     |         +----+
               | --------'    
               +---+          
A zeigt auf eine Liste, die Referenzen auf zwei Listen enthält, die jeweils zwei Referenzen auf das Objekt "0" enthälten. B zeigt hingegen auf eine Liste, die zwei Referenzen auf die selbe Liste enthält, die wiederum 2x das Objekt "0" referenziert.

Stefan
antimicro
User
Beiträge: 151
Registriert: Sonntag 29. Februar 2004, 16:24

ahh... krass

vielen Dank, alles klar soweit
greetings
sebi
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Schau dir den von mir verlinkten Thread an, dort steht die gesamte Geschichte in Form von Antworten und Verlinkungen zu anderen Threads / Blog Einträgen. Grundsätzlich geht es darum, daß man in Python nur mit Referenzen arbeitet und veränderliche (mutable) Objekte niemals eine Kopie erstellen (wenn nicht explizit angefordert), und du deswegen beim Malnehmen zweimal die selbe Liste in der Container Liste erhälst.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Eine Möglichkeit, kompakt ein "zweidimensionales Array" (das es in Python gar nicht gibt, sondern nur mit einer Liste von Listen simuliert werden kann) zu definieren, wäre dies:

Code: Alles auswählen

[[0] * 2 for i in range(2)]
Stefan
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

str1442 hat geschrieben:veränderliche (mutable) Objekte niemals eine Kopie erstellen (wenn nicht explizit angefordert)
Immutable genausowenig.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

@Leonidas Ich meinte das eigentlich in Bezug auf Methoden von veränderlichen Objekten, außer bei explizit gekennzeichneten Methoden (dict.copy() zb) - Okay, passt so gar nicht in den Kontext des Threads und meiner eigentlichen Aussage, habe ich allerdings geschrieben weil ich in dem Moment dran dachte :roll: :)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

sma hat geschrieben:Eine Möglichkeit, kompakt ein "zweidimensionales Array" (das es in Python gar nicht gibt, sondern nur mit einer Liste von Listen simuliert werden kann) ...
Das "nur" stimmt nicht ganz. Über dictionarys kann man auch etwas ähnliches erreichen, das sogar hinsichtlich der Notation beim Zugriff auf einzelne Elemente noch stärker an zweidimensionale Arrays erinnert, wie man sie aus diversen anderen Programmiersprachen kennt:

Code: Alles auswählen

In [15]: zelle = dict(zip([(x,y) for x in xrange(3) for y in xrange(4)],[0]*12))

In [16]: zelle[2,1] = 5

In [17]: zelle[1,2]
Out[17]: 0
Und wenn man Python 3.0 einsetzt, dann geht das mittels "Dictionary Comprehension" noch eleganter:

Code: Alles auswählen

>>> zelle = {(x,y):0 for x in range(3) for y in range(4)}
>>> zelle[2,1] = 5
>>> zelle[1,2]
0
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

numerix hat geschrieben:Das "nur" stimmt nicht ganz.
Zugegeben. Streiche "nur". Die Zugriffszeiten ist aber in der Regel schlechter. Wenn, dann würde ich vorschlagen, eine eigene Klassen mit passend überschriebenen __getitem__ und __setitem__ zu bauen, die das Koordinaten-Tupel serialisiert.

Stefan
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

sma hat geschrieben:
numerix hat geschrieben:Das "nur" stimmt nicht ganz.
Zugegeben. Streiche "nur". Die Zugriffszeiten ist aber in der Regel schlechter.
Das kann gut sein. Ich habe es selbst auch noch nie so gemacht (außer zu Experimentierzwecken) und - soweit ich mich erinnern kann - auch noch nie so in "echtem" Code gesehen. :)
BlackJack

@numerix: Noch zwei Varianten für Python <3, die IMHO etwas eleganter sind als das mit dem `zip()`:

Code: Alles auswählen

zs = dict.fromkeys(((x, y) for x in xrange(3) for y in xrange(4)), 0)
zs = dict((p, 0) for p in ((x, y) for x in xrange(3) for y in xrange(4)))
Was ist "echter" Code? Ich habe, wie so viele wahrscheinlich, mal mit Conway's Game Of Life rumexperimentiert, und ein `defaultdict`, das Koordinaten auf Zellen abbildet ist 'ne feine Sache, wenn man ein "unbegrenztes" Feld haben möchte, weil man Gleiter nicht gegen "Wände" laufen lassen möchte. :-)

Insgesamt bietet sich das immer an, wenn man sehr grosse "Arrays" hat, die aber nur sehr spärlich besetzt sind.
ch100

ich hatte seit tagen ein problem, und vor ca. ner stunde hab ich herausgefunden, dass es genau so ein problem ist, jetzt eben hab ich diesen thread gefunden :)

thx für die lösung :)
booth
User
Beiträge: 44
Registriert: Mittwoch 31. Oktober 2007, 21:30
Wohnort: Durham, U.K.

Hallo,

ich habe ein saudummes Problem und komme nicht drauf was ich falsch mache. Folgender Code:

Code: Alles auswählen

tstep = 10
arrayT = [[0]*8]*tstep
for ic in range(0,tstep):
    arrayT[ic][0] = float(ic)
    print arrayT[ic][0]
   
print arrayT
Das gibt: (natuerlich untereinander) 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
und dann das Array. ABER in dem Array ist die erste Spalte (also alle Zeilen) mit 9.0 gefuellt. Sollte aber 0.0 1.0 ... sein.

Frage: Warum?

Irgendwie bin ich zu doof.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Ähem steht doch schon in diesem Thread? Die Referenzen in arrayT zeigen alle auf ein Objekt.

Das ist übrigens kein Array sondern eine Liste und an PEP 8 hälst du dich auch nicht.
Antworten