Sollte ich 'has_key()' oder 'in' in Python-dicts?
Frage ich mich was besser ist zu tun:
d = {'a': 1, 'b': 2}
'a' in d
True
oder:
d = {'a': 1, 'b': 2}
d.has_key('a')
True
Du musst angemeldet sein, um einen Kommentar abzugeben.
Frage ich mich was besser ist zu tun:
d = {'a': 1, 'b': 2}
'a' in d
True
oder:
d = {'a': 1, 'b': 2}
d.has_key('a')
True
Du musst angemeldet sein, um einen Kommentar abzugeben.
in
ist definitiv mehr pythonic.In der Tat
has_key()
wurde entfernt in Python 3.x.in
arbeitet mit 2.6 zu Recht?keys()
ist nur ein Satz-wie der Blick in ein Wörterbuch eher als eine Kopie, sox in d.keys()
ist O(1). Dennochx in d
ist mehr Pythonic.x in d.keys()
so viel langsamer alsx in d
? (siehe die andere Antwort von @BrunoBronosky mit timeit läuft) Du hast Recht, obwohl es nicht angezeigt zu werden O(1), aber einen höheren Konstanten Faktor (ich sehe über 0.0361 vs 0.133 usec zwischen den beiden tut das timeit lokal testen, unabhängig davon, dict Größe in Python 3.7)x in d.keys()
müssen konstruieren und zu zerstören ein temporäres Objekt, komplett mit der Zuweisung von Speicher, bringt, wox in d.keys()
ist nur tun, eine arithmetische operation (Berechnung des hash) und macht einen lookup. Beachten Sie, dassd.keys()
ist nur etwa 10 mal so lang als dieses, die ist noch nicht wirklich lange. Ich habe nicht überprüft, aber ich bin immer noch ziemlich sicher, dass es nur O(1).in
gewinnt die Hände nach unten, nicht nur in der Eleganz (und nicht veraltet;-) aber auch in der Leistung, z.B.:Während die folgende Beobachtung ist nicht immer wahr, Sie werden feststellen, dass in der Regel, in Python, die schnellere Lösung ist mehr elegant und Pythonic; das ist, warum
-mtimeit
SO hilfreich ist-es ist nicht nur über das speichern von hundert Nanosekunden hier und dort!-)has_key
erscheint O(1) zu.Nach python docs:
Verwenden
dict.has_key()
wenn (und nur wenn) Ihr code wird benötigt, um lauffähig von Python-Versionen älter als 2.3 (wennkey in dict
eingeführt wurde).Es ist ein Beispiel, wo
in
eigentlich tötet Ihre Leistung.Wenn Sie
in
auf einer O(1) Behälter, die nur implementiert__getitem__
undhas_key()
aber nicht__contains__
Sie verwandeln eine O(1) Suche in O(N) Suche (wiein
fällt zurück auf eine lineare Suche über__getitem__
).Fix ist natürlich trivial:
has_key()
ist speziell für Python 2 Wörterbücher.in
/__contains__
ist die richtige API zu verwenden; für solche Behälter, wo ein vollständiger scan ist unvermeidlich, es gibt keinehas_key()
Methode trotzdem, und wenn es eine O(1) - Ansatz wählen, dann werden use-case spezifische und so dem Entwickler wählen Sie den richtigen Datentyp für das problem.has_key
einem dictionary-Methode, aberin
werden arbeiten an der Kollektion, und selbst wenn__contains__
fehlt,in
verwenden eine andere Methode zum Durchlaufen der Auflistung zu finden.in
tests aufrange
Objekte. Ich bin nicht so sicher über seine Effizienz auf Python 2xrange
, obwohl. 😉__contains__
können trivial berechnen, wenn ein Wert in dem Bereich oder nicht.1.0 in range(10**2, 0, -1)
und dann versuchen1.0 in range(10**10, 0, -1)
x in xrange(…)
, das ist eindeutig kein Python ist3 und deutlich eine schlechte Idee.xrange
aber während eine Menge Leute wissen das zu übersetzen, umrange()
in Python 3 nicht jeder ist sich bewusst, dass esrange()
containment-Test ist viel effizienter.Lösung dict.has_key() ist veraltet, verwenden Sie 'in' -- sublime text editor 3
Hier habe ich ein Beispiel-Wörterbuch mit dem Namen 'Alter' -
Erweiterung auf Alex Martelli ' s performance-tests mit Adam Parkin-Kommentare...
Wenn Sie so etwas wie dieses
ändern Sie unten läuft auf Python 3.X und höher
t.has_key(ew)
zurückTrue
wenn der Wertew
Referenzen ist auch ein Schlüssel im dictionary.key not in t
zurückTrue
wenn der Wert nicht im Wörterbuch. Außerdem, diekey = ew
alias ist sehr, sehr überflüssig. Die richtige Schreibweise istif ew in t
. Was die akzeptierte Antwort von 8 Jahren vor dir schon gesagt.