Seite 1 von 1

Liste wird in Funktion ohne Absicht verändert

Verfasst: Mittwoch 13. Juni 2012, 18:58
von Toonfish
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

Re: Liste wird in Funktion ohne Absicht verändert

Verfasst: Mittwoch 13. Juni 2012, 19:04
von deets
Templist ist keine *neue* liste. Sondern dieselbe die du übergibst, nur unter neuem Namen.

Zum kopieren zb in list() fassen.

Re: Liste wird in Funktion ohne Absicht verändert

Verfasst: Mittwoch 13. Juni 2012, 19:08
von EyDu
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

Re: Liste wird in Funktion ohne Absicht verändert

Verfasst: Mittwoch 13. Juni 2012, 19:11
von Toonfish
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

Re: Liste wird in Funktion ohne Absicht verändert

Verfasst: Mittwoch 13. Juni 2012, 19:19
von /me
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.