Ответ 1
in
определенно более pythonic.
Фактически has_key()
был удален в Python 3.x.
Интересно, что лучше делать:
d = {'a': 1, 'b': 2}
'a' in d
True
или
d = {'a': 1, 'b': 2}
d.has_key('a')
True
in
определенно более pythonic.
Фактически has_key()
был удален в Python 3.x.
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
так полезно - это не просто спасение сотен наносекунд здесь и там! -)
В соответствии с python docs:
has_key()
устарел в пользуkey in d
.
Используйте dict.has_key()
, если (и только если) ваш код должен быть запущен версиями Python раньше 2.3 (когда был введен key in dict
).
Есть один пример, где in
фактически убивает вашу производительность.
Если вы используете in
в контейнере O (1), который реализует только __getitem__
и has_key()
, но не __contains__
, вы превратите поиск O (1) в поиск O (N) (как in
возвращается к линейному поиску через __getitem__
).
Исправление очевидно тривиально:
def __contains__(self, x):
return self.has_key(x)
has_key
- метод словаря, но in
будет работать в любой коллекции, и даже если __contains__
отсутствует, in
будет использовать любой другой метод для итерации найденной коллекции.
Решение 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"
Python 2.x поддерживает has_key()
.
Поддержка Python 2.3+ и Python 3.x in
.
Развертывание тестов 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
Если вы намерены использовать значение по умолчанию, если ключ не находится в словаре, тогда
my_dict.get('key') or default_value
- это способ пропустить проверку in
. get
возвращает None
, если ключ не находится в словаре. Скорость также равна O (1), как при использовании in
.
Вы также можете использовать
my_dict.get('key', default_value)
но я считаю, что это менее читаемо.
Если у вас есть что-то вроде этого
t.has_key(ew)
измените его ниже для запуска на Python 3.X и выше
key = ew
if key not in t
В 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
Если вы можете написать код для использования индексации и обработки исключений, это может быть быстрее, чем проверка ключа, в зависимости от того, как часто вызывается исключение.
Определенно нет. Это было удалено на Python 3x
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)
>>>
Python 3.x
d = {'a': 1, 'b': 2}
if 'a' in d.keys():
#true condition
in
это, конечно, самый быстрый, самый чистый, самый лучший, самый короткий путь, чтобы сделать вещь также:
has_key
отсутствует в Python 3, так что используйтеin
конечно.
Кажется, в цепочку уже добавлено достаточно, но я хотел бы поделиться с ней немного подробнее. Как упоминалось ранее в комментариях, 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)
.
Обратите внимание, что скорость не имеет ничего общего с предпочтением. Читаемость важнее скорости, если вы не знаете, что находитесь на критическом пути.
На этот вопрос уже достаточно правильных ответов, но теперь у него есть награда с описанием:
Этот вопрос не получил достаточного внимания.
Я могу только повторить то же самое и написать из всех ответов лучший сборник:
Метод 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"