Wie kann "k in d" False sein, aber "k in d.keys ()" ist True?

7

Ich habe etwas Python-Code, der eine KeyError-Ausnahme auslöst. Bisher konnte ich mich außerhalb der Betriebsumgebung nicht reproduzieren, daher kann ich hier keinen reduzierten Testfall veröffentlichen.

Der Code, der die Ausnahme auslöst, durchläuft eine Schleife wie diese:

%Vor%

Die Zeile del[k] löst die Ausnahme aus. Ich habe eine try/except -Klausel hinzugefügt und konnte feststellen, dass k in d False ist, aber k in d.keys() ist True.

Die Schlüssel von d sind gebundene Methoden alter Klasseninstanzen.

Die Klasse implementiert __cmp__ und __hash__ , deshalb konzentriere ich mich auf meine Aufmerksamkeit.

    
Chris AtLee 27.10.2010, 17:50
quelle

4 Antworten

18

k in d.keys() testet die Gleichheit iterativ für jeden Schlüssel, während k in d __hash__ verwendet, also kann Ihre __hash__ gebrochen sein (d. h. es werden verschiedene Hashes für Objekte zurückgegeben, die gleich sind).

    
adw 27.10.2010, 17:59
quelle
5

Einfaches Beispiel für das, was gebrochen ist, für Interesse:

%Vor%     
katrielalex 27.10.2010 18:13
quelle
4

Löschen Sie keine Elemente in d , während Sie darüber iterieren, speichern Sie die zu löschenden Schlüssel in einer Liste und löschen Sie sie in einer anderen Schleife:

%Vor%     
Luper Rouch 27.10.2010 17:53
quelle
-1

Was Sie tun, würde in Java eine Ausnahme für eine gleichzeitige Änderung auslösen. d.keys() erstellt eine Liste der Schlüssel, so wie sie existieren, wenn Sie sie aufrufen, aber diese Liste ist jetzt statisch - Änderungen an d ändern eine gespeicherte Version von d.keys() nicht. Wenn Sie also über d.keys() iterieren, aber Elemente löschen, haben Sie die Möglichkeit, einen Schlüssel zu ändern, der nicht mehr vorhanden ist.

Sie können d.pop(k, None) verwenden, wodurch entweder der Wert k oder None zurückgegeben wird, wenn k nicht vorhanden ist. Dies vermeidet das Problem KeyError .

EDIT: Zur Klarstellung, um mehr Phantom Downmods zu verhindern (kein Problem mit negativen Feedback, einfach konstruktiv machen und einen Kommentar hinterlassen, so dass wir eine potenziell informative Diskussion haben können - ich bin hier, um zu lernen und zu helfen):

Es ist wahr, dass es in diesem speziellen Zustand nicht durcheinander gebracht werden sollte . Ich habe es nur als potentielles Problem erwähnt, denn wenn er in einem anderen Teil des Programms die gleiche Art von Codierungsschema verwendet, wo er nicht ist, so vorsichtig / glücklich darüber, wie er die Datenstruktur behandelt Solche Probleme könnten auftreten. Er benutzt nicht einmal ein Wörterbuch, sondern eine Klasse, die bestimmte Methoden implementiert, so dass Sie sie auf ähnliche Weise behandeln können.

    
nearlymonolith 27.10.2010 18:02
quelle

Tags und Links