Відповіді:
in безумовно, більш пітонічний.
Насправді has_key()був видалений в Python 3.x .
keys()це просто схожий набір у словник, а не копія, x in d.keys()як і O (1). Все-таки x in dє більш пітонічним.
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 швидше рішення є більш елегантним та пітонічним; ось чому -mtimeitТАК корисно - справа не лише в тому, щоб заощадити сто наносекунд тут і там! -)
has_keyвиявляється також O (1).
Згідно з документами python :
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 років до цього.