Должен ли я использовать has_key () или in в Python dicts? - PullRequest
822 голосов
/ 24 августа 2009

Интересно, что лучше сделать:

d = {'a': 1, 'b': 2}
'a' in d
True

или

d = {'a': 1, 'b': 2}
d.has_key('a')
True

Ответы [ 10 ]

1158 голосов
/ 24 августа 2009

in определенно более питонический.

Фактически has_key() было удалено в Python 3.x .

245 голосов
/ 24 августа 2009

in выигрывает, не только в элегантности (и не устаревающей ;-), но и в производительности, например ::10000 *

$ 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

Хотя следующее наблюдение не всегда верно, вы заметите, что обычно , в Python более быстрое решение более элегантно и Pythonic; Вот почему -mtimeit НАСТОЛЬКО полезен - это не , а о сохранении сотен наносекунд здесь и там! -)

88 голосов
/ 24 августа 2009

Согласно питону документы :

has_key() устарела в пользу key in d.

39 голосов
/ 25 августа 2009

Используйте dict.has_key(), если (и только если) ваш код должен быть запущен версиями Python ранее 2.3 (когда была введена key in dict).

21 голосов
/ 18 января 2012

Есть один пример, когда in фактически убивает вашу производительность.

Если вы используете in для контейнера O (1), который реализует только __getitem__ и has_key(), но не __contains__, вы превратите поиск O (1) в поиск O (N) (как in возвращается к линейному поиску через __getitem__).

Исправление очевидно тривиально:

def __contains__(self, x):
    return self.has_key(x)
15 голосов
/ 24 августа 2009

has_key - это словарный метод, но in будет работать с любой коллекцией, и даже если __contains__ отсутствует, in будет использовать любой другой метод для итерации коллекции, чтобы выяснить.

14 голосов
/ 23 февраля 2016

Решение dict.has_key () устарело, используйте 'in' - возвышенный текстовый редактор 3

Здесь я взял пример словаря «возраст» -

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"
11 голосов
/ 30 декабря 2016

Расширение тестов производительности Алекса Мартелли с комментариями Адама Паркина ...

$ 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
9 голосов
/ 09 мая 2012

Python 2.x поддерживает has_key().

Поддержка Python 2.3+ и Python 3.x in.

1 голос
/ 24 января 2017

Если у вас есть что-то вроде этого

t.has_key(ew)

измените его на ниже для работы на Python 3.X и выше

key = ew
if key not in t
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...