Antworten:
in
ist definitiv pythonischer.
In der Tat has_key()
wurde in Python 3.x entfernt .
keys()
nur eine satzartige Ansicht in ein Wörterbuch und keine Kopie x in d.keys()
. Trotzdem x in d
ist mehr pythonisch.
x in d.keys()
, dass ein temporäres Objekt erstellt und zerstört werden muss, einschließlich der damit verbundenen Speicherzuweisung, bei der x in d.keys()
nur eine arithmetische Operation (Berechnung des Hash) und eine Suche durchgeführt werden. Beachten Sie, dass dies d.keys()
nur etwa zehnmal so lang ist, was eigentlich immer noch nicht lange dauert. Ich habe nicht nachgesehen, bin mir aber ziemlich sicher, dass es nur O (1) ist.
in
gewinnt zweifellos, nicht nur in Eleganz (und nicht veraltet zu sein ;-), sondern auch in Leistung, zB:
$ python -mtimeit -s'd=dict.fromkeys(range(99))' '12 in d'
10000000 loops, best of 3: 0.0983 usec per loop
$ python -mtimeit -s'd=dict.fromkeys(range(99))' 'd.has_key(12)'
1000000 loops, best of 3: 0.21 usec per loop
Obwohl die folgende Beobachtung nicht immer zutrifft, werden Sie feststellen, dass in Python die schnellere Lösung normalerweise eleganter und pythonischer ist. Deshalb -mtimeit
ist es so hilfreich - es geht nicht nur darum, hier und da hundert Nanosekunden zu sparen! -)
has_key
scheint auch O (1) zu sein.
Laut Python- Dokumenten :
has_key()
wird zugunsten von abgelehntkey in d
.
has_key()
wird jetzt in Python 3
Verwenden dict.has_key()
Sie diese Option, wenn (und nur wenn) Ihr Code von Python-Versionen vor 2.3 (zum Zeitpunkt key in dict
der Einführung) ausgeführt werden muss.
Es gibt ein Beispiel, bei dem in
Ihre Leistung tatsächlich beeinträchtigt wird.
Wenn Sie in
einen O (1) -Container verwenden, der nur implementiert __getitem__
und has_key()
nicht __contains__
, wird eine O (1) -Suche in eine O (N) -Suche umgewandelt (da in
auf eine lineare Suche über zurückgegriffen wird __getitem__
).
Fix ist offensichtlich trivial:
def __contains__(self, x):
return self.has_key(x)
has_key()
ist spezifisch für Python 2-Wörterbücher . in
/ __contains__
ist die richtige API; Für Container, in denen ein vollständiger Scan unvermeidbar ist, gibt es ohnehin keine has_key()
Methode. Wenn es einen O (1) -Ansatz gibt, ist dieser anwendungsfallspezifisch, und der Entwickler muss den richtigen Datentyp für das Problem auswählen.
has_key
ist eine Wörterbuch Methode, sondern in
auf jeder Sammlung funktionieren wird, und selbst wenn __contains__
, fehlt in
wird eine andere Methode zu Iterierte die Sammlung verwenden , um herauszufinden.
in
Tests an range
Objekten durchzuführen . Ich bin mir jedoch nicht so sicher, wie effizient Python 2 xrange
ist. ;)
__contains__
kann trivial berechnen, ob ein Wert im Bereich liegt oder nicht.
range
jedes Mal eine neue Instanz zu erstellen . Bei Verwendung einer einzelnen, bereits vorhandenen Instanz ist der Test "Ganzzahl im Bereich" in meinen Timings etwa 40% schneller.
Die Lösung für dict.has_key () ist veraltet. Verwenden Sie 'in' - den erhabenen Texteditor 3
Hier habe ich ein Beispiel für ein Wörterbuch mit dem Namen "Alter" genommen -
ages = {}
# Add a couple of names to the dictionary
ages['Sue'] = 23
ages['Peter'] = 19
ages['Andrew'] = 78
ages['Karren'] = 45
# use of 'in' in if condition instead of function_name.has_key(key-name).
if 'Sue' in ages:
print "Sue is in the dictionary. She is", ages['Sue'], "years old"
else:
print "Sue is not in the dictionary"
Erweiterung der Leistungstests von Alex Martelli mit Adam Parkins Kommentaren ...
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 301, in main
x = t.timeit(number)
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
d.has_key(12)
AttributeError: 'dict' object has no attribute 'has_key'
$ python2.7 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0872 usec per loop
$ python2.7 -mtimeit -s'd=dict.fromkeys(range(1999))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0858 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' '12 in d'
10000000 loops, best of 3: 0.031 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d'
10000000 loops, best of 3: 0.033 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' '12 in d.keys()'
10000000 loops, best of 3: 0.115 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d.keys()'
10000000 loops, best of 3: 0.117 usec per loop
Wenn Sie so etwas haben:
t.has_key(ew)
Ändern Sie es für die Ausführung unter Python 3.X und höher wie folgt:
key = ew
if key not in t
t.has_key(ew)
Gibt zurück, True
wenn die Wertreferenzen ew
auch ein Schlüssel im Wörterbuch sind. key not in t
Gibt zurück, True
wenn der Wert nicht im Wörterbuch enthalten ist. Darüber hinaus ist der key = ew
Alias sehr, sehr redundant. Die richtige Schreibweise ist if ew in t
. Welches ist, was die akzeptierte Antwort von 8 Jahren zuvor Ihnen bereits gesagt hat.