Problem mit unerwünschter Modifikation von Variablen

Code-Stücke können hier veröffentlicht werden.
Antworten
physikant
User
Beiträge: 4
Registriert: Montag 14. April 2008, 10:44

Montag 14. April 2008, 10:56

Hall erstmal, ich bin neu in diesem Forum und auch noch Anfänger in der Programmierung von Python. Ich habe ein Problem mit der Funktion die ich unten aufgeführt habe. Die Funktion soll die Position des Maximums eines 2-spaltigen arrays bestimmen. Dieses liegt zwischen den zwei höchsten Werten und kann mittels eines kleinen Mathematischen Tricks bestimmt werden. Meine Formel geht davon aus, dass der dritte Punkt höher liegt als der erste. Tut er das nicht, vertausche ich diese beiden Punkte in einer loaklen Varieblen.

Das Problem ist, dass dann auch die globale Variable (die in der Funktion dann data heißt) verändert wird.

Kann mir jemand erklären wieso das passiert und wie man das verhindern kann.

Schonmal danke für eure Antworten.

Code: Alles auswählen

def peakguesser(data):
    point=zeros((3,2),type=Float)
    max=(0.0,0.0)
    maxpos=0
    for i in range(len(data)):
        if max[1]<data[i,1]:
            max=data[i]
            maxpos=i
    maxpos+=-1
    point=data[maxpos:maxpos+3]
    if point[2,1]>point[0,1]:
        interstore=point[0]
        point[0]=point[2]
        point[2]=interstore
    xintercept=point[2,0]-((point[2,0]-point[1,0])/(point[2,1]-point[1,1])*(point[2,1]-point[0,1]))
    return (xintercept+point[0,0])/2
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Montag 14. April 2008, 11:18

Hier wird deutlich, das Python immer mit Referenzen arbeitet. Z.B.:

Code: Alles auswählen

>>> a = [1, 2, 3] # a ist eine referenz auf [1, 2, 3]
>>> b = a         # b ist jetzt auch eine referenz auf [1, 2, 3]
>>> b[1] = 99
>>> print b
[1, 99, 3]
>>> print a
[1, 99, 3]
Beide Namen (a,b) zeigen in diesem Fall auf die gleiche Liste!

Wenn du mit einer Kopie arbeiten willst, kannst du das so machen:

Code: Alles auswählen

>>> b = list(a) # so...
>>> b = a[:]    # oder so...
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 14. April 2008, 11:37

Siehe auch:
mutable/immutable -> [wiki]Allgemeine Begriffe#M[/wiki]
http://www.python-forum.de/post-37245.html#37245

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Montag 14. April 2008, 11:45

Wenn es hier um Numpy-Arrays geht, gibt es wahrscheinlich einen besseren Weg als das so "komisch" zu Fuss zu machen.
physikant
User
Beiträge: 4
Registriert: Montag 14. April 2008, 10:44

Montag 14. April 2008, 12:05

Danke für die hilfreichen Antworten. Mir war nicht bewusst, dass da nur Verweise übergeben werden.

Es wird also ein Verweis in die Funktion übergeben, und die Liste ist veränderbar, damit besteht die Gefahr, dass ich ungewollt rumpfusche.

Nur verändere ich ja in meiner Funktion den Array 'data' nicht sondern nur den array point, welcher nach meinem Verständnis von Rebeccas Antwort nur eine Kopie eines Teils des Ausgangsarray ist. Oder sehe ich das falsch.

Code: Alles auswählen

point=data[maxpos:maxpos+3]
Auch danke für die links, ich werde mich da mal durchlesen.

@Blackjack: Ich mach das mit numarray. Was meinst du mit komisch zu Fuss?
BlackJack

Montag 14. April 2008, 12:59

Rebeccas Antwort gilt für Listen, aber nicht für `numarray`-Arrays, da bekommt man mit der "slice"-Notation einen "view" auf das Teilarray.

Mit "zu Fuss" meine ich die Schleife. Kann man das nicht eventuell mit `numarray`-Funktionen/Methoden lösen? `array.argmax()` zum Beispiel?
physikant
User
Beiträge: 4
Registriert: Montag 14. April 2008, 10:44

Montag 14. April 2008, 14:34

kann man auch, danke! Ich kannte die Funktion nicht, aber damit geht das natürlich eleganter und man muss das Rad ja nicht ständig neu erfinden.

Ok ich erzeuge also einen Verweis auf einen Ausschnitt der Ausgangsarrays. Wie kann ich denn stattdessen eine lokale Kopie erzeugen?
BlackJack

Montag 14. April 2008, 15:17

Die `copy()`-Funktion im `numarray`-Modul oder die `copy()`-Methode auf dem `array`-Exemplar erzeugen eine Kopie und der Konstruktor `array()` kopiert die Daten auch.
physikant
User
Beiträge: 4
Registriert: Montag 14. April 2008, 10:44

Montag 14. April 2008, 15:41

Dankeschön!

Das numarray hatte ich benutzt, weil ich das in einem Beispielprogramm schon gesehen hatte ohne auch nur annähernd alle funktionen zu kennen.
Antworten