In welcher Reihenfolge wird iteriert?

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
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

Hallo Gemeinde,

ich habe folgendes Problem und weiß nicht, wo ich sonst nach der Antwort suchen sollte.

Ich erzeuge eine Matrix, die 2D-Koordinaten enthält. Dazu erzeuge ich eine Liste, deren Einträge die Zeilen (oder Spalten, egal) der Matrix sind. Etwas so:

Code: Alles auswählen

StartwertMatrix = []
for i in range(-10, 1):                      
    StartwertMatrix.append([])                         
    for j in range(-10, 1):                    
        StartwertMatrix[-1].append([i, j])
Vielleicht kann man das Ergebnis eleganter erzeugen, ich bekomme jedenfalls, was ich will. Nun will ich zu jeder 2D-Koordinate aus meiner Matrix einen Ausgabewert erzeugen und diese Werte dann ausgeben. Die Ausgabewerte ermittle ich mit einem zweiten Skript, dass ich dazu aufrufe.

Code: Alles auswählen

from Datenerzeugung import *
Ergebnisliste = []
for Zeile in StartwertMatrix:
    Ergebnisliste.append([])
    for Eintrag in Zeile:
        Ausgabe = Datenerzeugung(Eintrag)
        Ergebnisliste[-1].append(Ausgabe)
Im Prinzip scheint die Sache zu funktionieren. Allerdings werden die Einträge der StartwertMatrix in einer scheinbar zufälligen Reihenfolge abgefragt. Ich denke, es liegt daran, dass die (externe) Datenerzeugung einige Zeit braucht. Muss ich meinem Skript in der Zwischenzeit sagen, dass es warten soll, oder was läuft hier?

Danke und Grüße, Tyrax
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Es wird in genau der Reihenfolge iteriert, in der du die Liste erzeugt hast, also von (-10, -10) ueber (-10, 0) zu (0,0).
Welche Reihenfolge erwartest du denn?

Dein Code ist etwas ungewoehnlich, vor allem, dass du erst Listen erzeugst und sie dann mit einem magischen Index ansprichst, statt die Liste einfach an einen Namen zu binden.

Code: Alles auswählen

>>> matrix = [ [[i,j] for j in range(-10, 1)] for i in range(-10,1)]
>>> StartwertMatrix == matrix
True
>>> matrix2 = list()
>>> for i in range(-10,1):
...     matrix2.append([[i,j] for j in range(-10,1)])
... 
>>> StartwertMatrix == matrix2
True
>>> matrix3 = list()
>>> for i in range(-10, 1):                      
...     row = list()
...     matrix3.append(row)
...     for j in range(-10, 1):                    
...         row.append([i,j])
...     
... 
>>> StartwertMatrix == matrix3
True
Von den Sternchenimporten ist auch abzuraten, vor allem wenn es ein Objekt darin gibt, das genauso heisst wie das Modul.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Da ändert sich keine Reihenfolge.

Code: Alles auswählen

>>> spam = [[(i, j) for j in range(5)] for i in range(5)]
>>> spam
[[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4)], [(1, 0), (1, 1), (1, 2), (1, 3), (1, 4)], [(2, 0), (2, 1), (2, 2), (2, 3), (2, 4)], [(3, 0), (3, 1), (3, 2), (3, 3), (3, 4)], [(4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]]
>>> map(lambda row: map(lambda (u, v): u*v, row), spam)                                    
[[0, 0, 0, 0, 0], [0, 1, 2, 3, 4], [0, 2, 4, 6, 8], [0, 3, 6, 9, 12], [0, 4, 8, 12, 16]]
Und wirf doch bitte einen Blick in PEP 8. Besonders was Bezeichner angeht.
Das Leben ist wie ein Tennisball.
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

Hallo cofi und EyDu,

und danke für die Beispiele zur Matrixerzeugung. Ich habe in meinen for Schleifen zu Anfang meist noch 'ne print Anweisung drin, die mir verrät, ob alles so läuft, wie ich mir das vorstelle. Daher der längliche Code.

Ich habe auch erwartet, dass die Einträge der Liste in der Reihenfolge abgearbeitet werden, wie sie in der Liste stehen. Wenn ich statt der externen Datenerzeugung einen Dummy-Eintrag setzen lasse, funktioniert das auch. Wenn ich die externe Datenerzeugung nutze, scheint die Reihenfolge sich zufällig zu ändern. Es kommen sogar unterschiedliche Reihenfolgen für gleiche Anfangsparameter.

Ich suche jetzt erstmal weiter nach Fehlern (und lese PEP 8 ).

Grüße, Tyrax
BlackJack

@Tyrax: Was bedeutet "externe Datenerzeugung"? Kann es sein, dass da einfach immer andere Matrixdaten erzeugt werden?
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

Hallo,

ich bin dem Fehler jetzt näher, der Lösung nicht unbedingt. Ich beschreibe mal, was ich tue und was passiert. Vielleicht mache ich grundsätzlich was falsch.

Ich habe (im wesentlichen) zwei Skripte: main.py und Datenerzeugung.py

Datenerzeugung.py enthält eine Funktion. main.py bekommt eine Liste von Anfangsbedingungen in Form der oben genanten Matrix, und ruft mit jedem Matrixeintrag die Funktion aus Datenerzeugung.py auf. Per return-Anweisung bekommt main.py die Ergebnisse zurück und schreibt diese in eine (Bildschirm-)Ausgabe.

Der Funktionsaufruf durch main.py steht in der for-Schleife. In jedem Schleifendurchlauf wird die Funktion benutzt um ein Ergebnis zu erzeugen. Und jetzt endet mein Verständnis. Der Code

Code: Alles auswählen

Laufzeitmatrix = []
for Zeile in StartwertMatrix:
    Laufzeitmatrix.append([]) 
    for Eintrag in Zeile:
        xx = Eintrag
        yy = Eintrag
        print 'Eintrag vorher = ', Eintrag
        Funktionsausgabe = meinefunktion(xx, yy)
        print 'Eintrag nachher = ', Eintrag
gibt zweimal die Variable 'Eintrag' per print-Anweisung aus. Einmal vor der Ausführung meiner Funktion, einmal danach. Der Name Eintrag taucht hier und nirgendwo sonst in meinen Skripten auf. Trotzdem ist der Wert von 'Eintrag' vor und nach der Funtionsauswertung verschieden. Daher kommt dann das Chaos in meiner Ausgabe.

Ich verstehe es nicht.

Danke und Grüße, Tyrax
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dann ist "Eintrag" wahrscheinlich nicht immutable und du änderst es in "meinefunktion".
Das Leben ist wie ein Tennisball.
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

Aber wie tue ich das, wo Eintrag doch in meinefunktion gar nicht vorkommt?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Bei dem letzten code sind sowohl `xx` als auch `yy` dieselbe Liste (ich glaube das ist nicht gewuenscht, oder?) und die wird `meinefunktion` uebergeben. Listen sind veraenderbar und deshalb wird jede veraenderung durch `meinefunktion` auch in `startmatrix` wieder auftauchen.
BlackJack

@Tyrax: Der Name kommt in der Funktion nicht vor, aber das Listenobjekt übergibst Du ja. Vielleicht hilft das hier ja beim Verständnis:

Code: Alles auswählen

In [451]: xs = [0, 0, 0]

In [452]: ys = xs

In [453]: ys[0] = 42

In [454]: xs
Out[454]: [42, 0, 0]

In [455]: ys
Out[455]: [42, 0, 0]

In [456]: xs[1] = 23

In [457]: xs
Out[457]: [42, 23, 0]

In [458]: ys
Out[458]: [42, 23, 0]
`xs` und `ys` sind zwei Namen für die *selbe* Liste. Und wenn Du die Liste veränderst, dann ist das natürlich über beide Namen sichtbar -- weil's eben die selbe Liste ist. Wenn Du Objekte in einer Funktion veränderst, solltest Du Dich immer fragen ob der Aufrufer damit wohl rechnet dass das passiert. Falls nicht, solltest Du eine Kopie erstellen. Wenn in der Funktion der Grossteil der Werte in der Matrix verändert wird, würde ich für's Kopieren keinen Extraschritt vorsehen, sondern aus den alten Daten eine neue Datenstruktur aufbauen.
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

Verdammt noch eins, das muss es sein. Und ich suche die ganze Zeit nach einem tieferliegenden Fehler, und dann sind es wieder die basics, die mich ausbremsen.

Danke Euch allen, Tyrax

edit:
P.S.: Warum möchte man eigentlich einem Objekt verschiedene Namen geben können?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Tyrax hat geschrieben:P.S.: Warum möchte man eigentlich einem Objekt verschiedene Namen geben können?
Damit sowas möglich ist:

Code: Alles auswählen

a = 3
def square(n):
   return n * n
square(a)
Das an ``a`` gebundene Objekt wird zwischendrin auch an den Namen ``n`` gebunden, hat also mehr als einen Namen zur gleichen Zeit.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten