Відповіді:
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 років до цього.