Seite 1 von 1

mehrdimensionale Arrays

Verfasst: Samstag 27. Dezember 2008, 19:08
von antimicro
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

Verfasst: Samstag 27. Dezember 2008, 19:16
von str1442
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

Verfasst: Samstag 27. Dezember 2008, 19:17
von antimicro
Hi,
ja okay, sollten sie doch aber, oder? Ich hab doch auf beiden die gleiche Operation durchgeführt, oder nicht...

Re: mehrdimensionale Arrays

Verfasst: Samstag 27. Dezember 2008, 19:20
von sma
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

Verfasst: Samstag 27. Dezember 2008, 19:24
von antimicro
ahh... krass

vielen Dank, alles klar soweit

Verfasst: Samstag 27. Dezember 2008, 19:25
von str1442
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.

Verfasst: Samstag 27. Dezember 2008, 19:37
von sma
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

Verfasst: Samstag 27. Dezember 2008, 20:09
von Leonidas
str1442 hat geschrieben:veränderliche (mutable) Objekte niemals eine Kopie erstellen (wenn nicht explizit angefordert)
Immutable genausowenig.

Verfasst: Samstag 27. Dezember 2008, 20:26
von str1442
@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: :)

Verfasst: Sonntag 28. Dezember 2008, 20:37
von numerix
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

Verfasst: Montag 29. Dezember 2008, 10:01
von sma
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

Verfasst: Montag 29. Dezember 2008, 12:53
von numerix
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. :)

Verfasst: Dienstag 30. Dezember 2008, 15:34
von 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.

Verfasst: Donnerstag 1. Januar 2009, 03:54
von 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 :)

Arrays in FOR-Schleife beschreiben

Verfasst: Montag 9. Februar 2009, 19:05
von booth
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.

Verfasst: Montag 9. Februar 2009, 19:11
von DasIch
Ä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.