Должен ли я использовать has_key() или in в Python dicts?

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

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

или

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

Ответы

Ответ 2

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

$ 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 так полезно - это не просто спасение сотен наносекунд здесь и там! -)

Ответ 3

В соответствии с python docs:

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

Ответ 4

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

Ответ 5

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

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

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

def __contains__(self, x):
    return self.has_key(x)

Ответ 6

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

Ответ 7

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

Здесь я привел пример словаря с именем "age" -

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"

Ответ 8

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

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

Ответ 9

Развертывание тестов Alex Martelli с комментариями Адама Паркина...

$ 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

Ответ 10

Если вы намерены использовать значение по умолчанию, если ключ не находится в словаре, тогда

my_dict.get('key') or default_value

- это способ пропустить проверку in. get возвращает None, если ключ не находится в словаре. Скорость также равна O (1), как при использовании in.

Вы также можете использовать

my_dict.get('key', default_value)

но я считаю, что это менее читаемо.

Ответ 11

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

t.has_key(ew)

измените его ниже для запуска на Python 3.X и выше

key = ew
if key not in t

Ответ 12

В v/s has_key()

Помимо амортизации "In" в последней версии Python, я думаю, что "ключ в dict" быстрее, чем "dict.has_key()", потому что он избегает поиска атрибутов для has_key(). Хотя, если вы ищете ключи в цикле, вы можете вывести поиск из цикла с помощью чего-то вроде:

d = {}
hk = d.has_key
for i in someList:
  if hk(i):
    # do something if i is in d

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

Ответ 13

Определенно нет. Это было удалено на Python 3x

Ответ 14

API выглядит так, как он по какой-то причине... Использование встроенных API-интерфейсов, как описано в Pythonic...

Обычно вы должны делать my_dict.get('key', default_value), а не my_dict.get('key') or default_value.

Исключением будет нечетный случай, чтобы заменить все значения с ложным эквивалентом (0, '', [] и т.д.), возвращенные с my_dict с помощью default_value.

Собственно, если целью является получение значения по умолчанию из dict, почему бы не использовать collections.defaultdict вместо встроенного dict?

>>> from collections import defaultdict
>>> d42 = defaultdict(lambda: 42)
>>> d42['x'] = 18
>>> d42['x']
18
>>> d42['y']
42

Чаще всего usecase для defaultdicts, вероятно, относится к типу списка, например:

>>> dl = defaultdict(list)
>>> for x, y in some_list_of_tuples:
...     dl[x].append(y)
>>>

Ответ 15

Python 3.x

d = {'a': 1, 'b': 2}
if 'a' in d.keys():
    #true condition

Ответ 16

in это, конечно, самый быстрый, самый чистый, самый лучший, самый короткий путь, чтобы сделать вещь также:

has_key отсутствует в Python 3, так что используйте in конечно.

Ответ 17

Кажется, в цепочку уже добавлено достаточно, но я хотел бы поделиться с ней немного подробнее. Как упоминалось ранее в комментариях, has_key устарела, но даже тогда я нахожу, что обе эти операции выполняют одно и то же: проверяют хеш-таблицу, реализованную в dict для ключа. Ни один из них не будет повторять весь словарь. Имейте в виду, что for x in dict отличается от if x in dict. Они оба используют ключевое слово in, но это разные операции.

Ключевое слово in становится вызовом dict.__contains__, которое dict может реализовать, как ему нравится.

Если есть различие во времени этих операций, оно будет очень маленьким и будет связано с накладными расходами вызова функции has_key.

К тому времени, когда вы придете к этому посту, предпочтение key in dict будет для вас очень ясным (по всем упомянутым причинам). Это общее предпочтение (должно быть) наиболее важно из-за более четкого выражения намерения, чем dict.has_key(key).

Обратите внимание, что скорость не имеет ничего общего с предпочтением. Читаемость важнее скорости, если вы не знаете, что находитесь на критическом пути.

Ответ 18

На этот вопрос уже достаточно правильных ответов, но теперь у него есть награда с описанием:

Этот вопрос не получил достаточного внимания.

Я могу только повторить то же самое и написать из всех ответов лучший сборник:

Метод has_key() был удален в Python 3.x.
Это официальная информация от docs.python.org :

Удалены. dict.has_key() - используйте вместо этого оператор in.

Вы должны использовать in операторе следующим образом:

mydict = {'a': 1, 'b': 2}

if 'a' in mydict:

    print "Key a is in the dictionary. It has ", mydict ['a'], " as value"

else:

    print "Key a is not in the dictionary"