Liste wird in Funktion ohne Absicht verändert

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
Toonfish
User
Beiträge: 2
Registriert: Mittwoch 13. Juni 2012, 18:44

Hey Leute,

ich wollte mir heute mal fix ein kleines Programm schreiben und stieß dabei auf folgendes Problem:
Hier mal das Codesegment (alle nötigen imports sind vorhanden):

Code: Alles auswählen

Solutions = [5,6,25,76,376]

def get_highest_element_with_unit_position(List, unit_pos):
    TempList = List
    while round(10 * (max(TempList) / 10 - math.floor(max(TempList) / 10))) != UnitPos:
        TempList.remove(max(TempList))
    return max(TempList)
Ziel davon ist es, das größte Element der Liste zu finden, welches an der Einerstelle die gewünschte Zahl hat. (UnitPos ist die Einerstelle)
Jedenfalls wenn ich jetzt in der Shell

GetHighestElementWithUnitPosition(Solutions, 5)

ausführe, so erhalte ich 25, so weit so gut. Nach dem Durchlaufen der While-Schleife sieht die TempList so aus: [5,6,25]
Allerdings hat sich jetzt auch die Liste Solutions auf genau diese Elemente, obwohl meiner Meinung nach dazu nichts im Code steht um dies zu erreichen. Eigentlich wird ja nur die TempList verändert und die wird am Anfang der Funktion abgefragt.
Wenn ich nun

GetHighestElementWithUnitPosition(Solutions, 6)

verwende, so erhalte ich 6 als Ergebnis, da eben die Liste Solutions die Elemente 76 und 376 nicht mehr enthält.

Entweder hab ich zu lange kein Python mehr gehabt oder ich bin einfach zu blöd und seh nicht warum Solutions auch verändert wird, könnt ihr mir weiterhelfen?

Vielen Dank im Voraus, Toonfish
Zuletzt geändert von Toonfish am Mittwoch 13. Juni 2012, 19:27, insgesamt 4-mal geändert.
deets

Templist ist keine *neue* liste. Sondern dieselbe die du übergibst, nur unter neuem Namen.

Zum kopieren zb in list() fassen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Da hast du eine entscheidene Eigenschaft von Python wahrscheinlich nicht richtig erfasst. Bei einer Zuweisung werden immer nur Referenzen koiert, niemals die Daten. Das muss man immer explizit machen Wenn du also schreibst:

Code: Alles auswählen

liste_neu = liste_alt
Dann ist liste_neu GENAU DIE SELBE Liste wie liste_alt. Du kannst es dir so vorstellen, dass liste_neu und liste_alt zwei Namen sind, welche auf das selbe Objekt zeigen. Wenn du eine Kopie möchtest, dann benutze:

Code: Alles auswählen

liste_neu = liste_alt[:]
Aber auch hier musst du vorsichtig sein! Es werden nur die Referenzen in der Liste kopiert und nicht zum Beispiel die Listen in Listen. Probiere damit einfach mal ein wenig rum.

Zu deinem Ansatz muss man allerdings sagen, dass dieser gar keine remove braucht. Am besten erstellst du dir eine NEUE Liste, welche alle Erlaubten elemente enhält und suchst darin das Maximum. Mit Generatorausdrücken kann man das doch etwas kompakter machen, aber das ist für dich erstmal nicht so wichtig.

Weiter solltest du noch einen Blick in PEP 8 werfen, das ist der Style-Guide von Python. Den solltest du am besten einhalten (hier sind es vorallem die Namen), das vereinfacht die Kommunikation ein wenig, da die Schreibweise von Namen bereits etwas über den Kontext aussagt.

Sebastian
Das Leben ist wie ein Tennisball.
Toonfish
User
Beiträge: 2
Registriert: Mittwoch 13. Juni 2012, 18:44

Ahh vielen Dank für die schnellen Antworten. Jetzt funktioniert alles wunderbar.

Ich hatte Python mal vor einer halben Ewigkeit angefangen, und wollte jetzt mal wieder einsteigen, das hatte ich dann wohl vergessen, dass die Listen komplett gleichgesetzt werden, danke nochmal, auch der PEP 8 Guide ist sehr hilfreich :D
Zuletzt geändert von Toonfish am Mittwoch 13. Juni 2012, 19:24, insgesamt 2-mal geändert.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

EyDu hat geschrieben:Zu deinem Ansatz muss man allerdings sagen, dass dieser gar keine remove braucht. Am besten erstellst du dir eine NEUE Liste, welche alle Erlaubten elemente enhält und suchst darin das Maximum. Mit Generatorausdrücken kann man das doch etwas kompakter machen, aber das ist für dich erstmal nicht so wichtig.

Weiter solltest du noch einen Blick in PEP 8 werfen, das ist der Style-Guide von Python. Den solltest du am besten einhalten (hier sind es vorallem die Namen), das vereinfacht die Kommunikation ein wenig, da die Schreibweise von Namen bereits etwas über den Kontext aussagt.
Um das mal in Code zu gießen :

Code: Alles auswählen

solutions = [5, 6, 25, 76, 376]

def get_highest_element_with_unit_position(iterable, unit_pos):
    return max(value for value in iterable if str(value)[-1] == str(unit_pos))

print get_highest_element_with_unit_position(solutions, 5)
Man muss nur noch den Fall eines leeren Iterable abfangen.
Antworten