Ответы:
in
определенно более питонический.
На самом деле has_key()
был удален в Python 3.x .
keys()
это просто набор-подобный вид словаря, а не его копия, x in d.keys()
как и O (1). Тем не менее, x in d
более Pythonic.
x in d.keys()
должен создать и уничтожить временный объект, в комплекте с распределением памяти, которое влечет за собой, где x in d.keys()
просто делает арифметическую операцию (вычисление хеша) и делает поиск. Обратите внимание, что d.keys()
это примерно в 10 раз больше, чем на самом деле. Я не проверял, но я все еще уверен, что это только O (1).
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
ТАК полезно - это не просто экономия сотен наносекунд здесь и там! -)
has_key
Похоже, O (1) тоже.
Согласно документации по питону :
has_key()
не рекомендуется в пользуkey in d
.
has_key()
теперь удален в Python 3
Используйте, 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()
является специфическим для Python 2 словарей . in
/ __contains__
является правильным API для использования; для тех контейнеров, где полное сканирование неизбежно, в любом случае нет никакого has_key()
метода , и если есть подход O (1), то это будет зависеть от варианта использования, и поэтому разработчик должен выбрать правильный тип данных для проблемы.
has_key
это словарный метод, но он in
будет работать с любой коллекцией, и даже если __contains__
он отсутствует, in
будет использовать любой другой метод для итерации коллекции, чтобы выяснить это.
in
тесты на range
объектах. Однако я не уверен в его эффективности на Python 2 xrange
. ;)
__contains__
может тривиально вычислить, находится ли значение в диапазоне или нет.
range
экземпляра каждый раз. При использовании одного ранее существующего экземпляра тест "целое число в диапазоне" выполняется примерно на 40% быстрее.
Решение 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"
Расширяя тесты производительности Алекса Мартелли с комментариями Адама Паркина ...
$ 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
Если у вас есть что-то вроде этого:
t.has_key(ew)
измените его на ниже для работы на Python 3.X и выше:
key = ew
if key not in t
t.has_key(ew)
возвращает, True
если значение ew
ссылки также является ключом в словаре. key not in t
возвращает, True
если значение отсутствует в словаре. Более того, key = ew
псевдоним очень, очень избыточен. Правильное написаниеif ew in t
. Вот что уже сказал вам принятый ответ за 8 лет до этого.