Odpowiedzi:
in
jest zdecydowanie bardziej pytoniczny.
W rzeczywistości has_key()
usunięto Python 3.x .
keys()
jest tylko zestawem widoków na słownik, a nie na kopie, podobnie jak x in d.keys()
O (1). Mimo x in d
to jest bardziej Python.
x in d.keys()
musi skonstruować i zniszczyć obiekt tymczasowy, wraz z przydziałem pamięci, który pociąga za sobą, w którym x in d.keys()
po prostu wykonuje operację arytmetyczną (obliczanie skrótu) i wykonuje wyszukiwanie. Zauważ, że d.keys()
jest to tylko około 10 razy dłużej niż to, co tak naprawdę nie jest długie. Nie sprawdziłem, ale wciąż jestem pewien, że to tylko O (1).
in
wygrywa wręcz, nie tylko w elegancji (i nie jest przestarzały ;-), ale także w wydajności, np .:
$ 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
Chociaż poniższe obserwacje nie zawsze są prawdziwe, zauważysz, że zwykle w Pythonie szybsze rozwiązanie jest bardziej eleganckie i Pythoniczne; dlatego -mtimeit
jest tak pomocny - nie chodzi tylko o zaoszczędzenie setek nanosekund tu i tam! -)
has_key
wydaje się być również O (1).
Według dokumentów Pythona :
has_key()
jest przestarzałe na korzyśćkey in d
.
has_key()
jest teraz usunięty w Python 3
Użyj dict.has_key()
jeśli (i tylko jeśli) twój kod musi być uruchamiany przez wersje Pythona wcześniejsze niż 2.3 (kiedy key in dict
został wprowadzony).
Jest jeden przykład, w którym in
faktycznie zabija twoją wydajność.
Jeśli używasz in
w czasie O (1) pojemnik, że tylko narzędzia __getitem__
i has_key()
ale nie __contains__
można włączyć O (1) szukaj w O (N) wyszukiwania (jak in
wraca do wyszukiwania poprzez liniowy __getitem__
).
Naprawienie jest oczywiście trywialne:
def __contains__(self, x):
return self.has_key(x)
has_key()
jest specyficzny dla słowników Python 2 . in
/ __contains__
to właściwy interfejs API do użycia; dla tych pojemników w których pełne skanowanie jest nieuniknione, nie jest has_key()
metoda i tak , a jeśli nie jest O (1) Podejście wtedy będzie use-case specyficzny i tak aż do dewelopera, aby wybrać odpowiedni typ danych dla tego problemu.
has_key
jest metodą słownikową, ale in
będzie działać na dowolnej kolekcji, a nawet gdy jej __contains__
brakuje, in
użyje dowolnej innej metody, aby iterować kolekcję, aby się dowiedzieć.
in
testów na range
obiektach jest dość wydajne . Nie jestem jednak pewien jego wydajności w Pythonie 2 xrange
. ;)
__contains__
Potrafi w prosty sposób obliczyć, czy wartość mieści się w zakresie, czy nie.
range
instancji za każdym razem. Używając jednej, istniejącej wcześniej instancji, test „liczby całkowitej w zakresie” jest o około 40% szybszy w moich momentach.
Rozwiązanie dict.has_key () jest przestarzałe, użyj „in” - wysublimowanego edytora tekstu 3
Tutaj wziąłem przykład słownika o nazwie „wiek” -
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"
Rozszerzanie testów wydajności Alexa Martellego o komentarze Adama Parkina ...
$ 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
Jeśli masz coś takiego:
t.has_key(ew)
zmień go poniżej, aby uruchomić na Pythonie 3.X i nowszych:
key = ew
if key not in t
t.has_key(ew)
zwraca, True
jeśli ew
odwołania do wartości są również kluczem w słowniku. key not in t
zwraca, True
jeśli wartości nie ma w słowniku. Co więcej, key = ew
alias jest bardzo, bardzo zbędny. Prawidłowa pisownia to if ew in t
. Tak powiedziała już zaakceptowana odpowiedź sprzed 8 lat.