Проверить, существует ли уже данный ключ в словаре

avatar
Mohan Gulati
21 октября 2009 в 19:05
4601902
16
2679

Я хотел проверить, существует ли ключ в словаре, прежде чем обновлять значение для ключа. Я написал следующий код:

if 'key1' in dict.keys():
  print "blah"
else:
  print "boo"

Я думаю, что это не лучший способ выполнить эту задачу. Есть ли лучший способ проверить ключ в словаре?

Источник
Evgeni Sergeev
12 августа 2013 в 08:51
31

Вызов dict.keys() создает список ключей согласно документации docs.python.org/2/library/stdtypes.html#dict.keys, но я был бы удивлен, если бы этот шаблон не был оптимизирован ибо в серьезной реализации преобразовать в if 'key1' in dict:.

Evgeni Sergeev
12 августа 2013 в 08:58
7

Итак, я наконец выяснил, почему многие из моих скриптов Python были такими медленными :) :(. Это потому, что я использовал x in dict.keys() для проверки ключей. И это произошло потому, что обычный способ перебора ключей в Java - for (Type k : dict.keySet()), эта привычка заставляет for k in dict.keys() казаться более естественным, чем for k in dict (что по-прежнему должно быть хорошо с точки зрения производительности?), но тогда проверка ключей тоже становится if k in dict.keys(), что является проблемой ...

ToolmakerSteve
16 декабря 2013 в 23:34
4

@EvgeniSergeev if k in dict_: проверяет наличие k в КЛЮЧАХ dict_, поэтому вам все равно не нужен dict_.keys(). (Это меня укусило, так как мне кажется, что это тестирование для значения в dict. Но это не так.)

Evgeni Sergeev
17 декабря 2013 в 01:51
1

@ToolmakerSteve Верно, но это не только вам не нужно, но и плохая практика.

marcelosalloum
26 июня 2014 в 17:18
26

Попробуйте "ввести dict"

Ответы (16)

avatar
Chris B.
21 октября 2009 в 19:10
4318

in - это предполагаемый способ проверки наличия ключа в dict.

d = {"key1": 10, "key2": 23}

if "key1" in d:
    print("this will execute")

if "nonexistent key" in d:
    print("this will not")

Если вам нужно значение по умолчанию, вы всегда можете использовать dict.get():

d = dict()

for i in range(100):
    key = i % 10
    d[key] = d.get(key, 0) + 1

, и если вы хотите всегда обеспечивать значение по умолчанию для любого ключа, вы можете использовать dict.setdefault() несколько раз или defaultdict из > модуль, например:

from collections import defaultdict

d = defaultdict(int)

for i in range(100):
    d[i % 10] += 1

, но в целом ключевое слово in - лучший способ сделать это.

Jason Baker
21 октября 2009 в 19:12
82

Обычно я просто использую get, если все равно собираюсь вытащить элемент из словаря. Нет смысла использовать in и для извлечения элемента из словаря.

Chris B.
21 октября 2009 в 19:16
83

Я полностью согласен. Но если вам нужно только знать, существует ли ключ, или вам нужно различать случай, когда ключ определен, и случай, когда вы используете значение по умолчанию, in - лучший способ сделать это.

enkash
28 января 2015 в 05:54
5

Ссылка для этого ответа находится в документации python

yaobin
23 июля 2015 в 13:00
0

@enkash предоставил ссылку на Python 3. Вот ссылка на Python 2.7: dict и dict.get.

Sebastien
9 февраля 2016 в 21:06
41

get - плохой тест, если ключ эквивалентен "False", например, 0. Я усвоил это на собственном горьком опыте: /

Craig Hicks
5 октября 2017 в 01:18
5

Я не могу согласиться с тем, что это полный ответ, поскольку в нем не упоминается, что «попробовать» - «кроме» будет самым быстрым, когда количество сбоев ключа достаточно мало. См. Этот ответ ниже: coderhelper.com/a/1602945/4376643

Gabriel Staples
23 марта 2020 в 06:47
0

Вы, вероятно, также должны упомянуть, что dict.has_key(), , как описано здесь в Tutorialspoint, например,, устарел в Python3: «Удалено. Dict.has_key ()8277 - используйте <1295655 > вместо этого оператора ".

mbyamukama
27 июля 2020 в 16:54
0

очевидно, что второй оператор печати в этом примере не будет выполняться!

TheSHETTY-Paradise
28 февраля 2021 в 14:04
0

с использованием if "key1" in d имеет временную сложность O (n), поскольку «key1» будет соответствовать каждому элементу в ключах dict. Вместо этого используйте try и except KeyError и напрямую обращайтесь к d ["key1"], если он существует, вы получите значение, иначе это вызовет ошибку, о которой также позаботится оператор except :) Следовательно, это происходит в постоянное время!

avatar
prosti
23 мая 2019 в 20:14
14

Проверить, существует ли уже данный ключ в словаре

Чтобы понять, как это сделать, мы сначала проверяем, какие методы мы можем вызывать для словаря. Вот методы:

d={'clear':0, 'copy':1, 'fromkeys':2, 'get':3, 'items':4, 'keys':5, 'pop':6, 'popitem':7, 'setdefault':8, 'update':9, 'values':10}

Python Dictionary clear()       Removes all Items
Python Dictionary copy()        Returns Shallow Copy of a Dictionary
Python Dictionary fromkeys()    Creates dictionary from given sequence
Python Dictionary get()         Returns Value of The Key
Python Dictionary items()       Returns view of dictionary (key, value) pair
Python Dictionary keys()        Returns View Object of All Keys
Python Dictionary pop()         Removes and returns element having given key
Python Dictionary popitem()     Returns & Removes Element From Dictionary
Python Dictionary setdefault()  Inserts Key With a Value if Key is not Present
Python Dictionary update()      Updates the Dictionary 
Python Dictionary values()      Returns view of all values in dictionary

Жестоким методом проверки наличия ключа может быть метод get():

d.get("key")

Два других интересных методов items() и keys() кажутся слишком трудоемкими. Итак, давайте посмотрим, подходит ли нам метод get(). У нас есть наш dict d:

d= {'clear':0, 'copy':1, 'fromkeys':2, 'get':3, 'items':4, 'keys':5, 'pop':6, 'popitem':7, 'setdefault':8, 'update':9, 'values':10}

Печать показывает, что ключ, которого у нас нет, вернет None:

print(d.get('key')) #None
print(d.get('clear')) #0
print(d.get('copy')) #1

Мы можем использовать это, чтобы получить информацию, присутствует ли ключ или нет. Но учтите это, если мы создадим dict с одним key:None:

d= {'key':None}
print(d.get('key')) #None
print(d.get('key2')) #None

Указание на то, что метод get() ненадежен, если некоторые значения могут быть None. У этой истории должен быть более счастливый конец. Если мы используем компаратор in:

print('key' in d) #True
print('key2' in d) #False

Получаем верные результаты. Мы можем проверить байт-код Python:

import dis
dis.dis("'key' in d")
#   1           0 LOAD_CONST               0 ('key')
#               2 LOAD_NAME                0 (d)
#               4 COMPARE_OP               6 (in)
#               6 RETURN_VALUE

dis.dis("d.get('key2')")
#   1           0 LOAD_NAME                0 (d)
#               2 LOAD_METHOD              1 (get)
#               4 LOAD_CONST               0 ('key2')
#               6 CALL_METHOD              1
#               8 RETURN_VALUE

Это показывает, что in оператор сравнения не только надежнее, но даже быстрее, чем get().

Alex
5 июля 2019 в 09:36
0

.get() может иметь второй аргумент для значения default, который можно использовать для решения проблемы, когда key:None. пример: d.get("key", False)

HCLivess
30 декабря 2019 в 20:34
0

.get() - самый быстрый способ. Другой вариант - назначить в блоке try / except

avatar
J. Antunes
27 апреля 2019 в 23:30
6

Совместное использование еще одного способа проверки наличия ключа с помощью логических операторов.

d = {'a': 1, 'b':2}
keys = 'abcd'

for k in keys:
    x = (k in d and 'blah') or 'boo'
    print(x) 

Это возвращает

>>> blah
>>> blah
>>> boo
>>> boo

Пояснение

Сначала вы должны знать, что в Python, 0, None или объекты с нулевой длиной оцениваются как False. Все остальное оценивается как True. Логические операции выполняются слева направо и возвращают операнд, отличный от True или False.

Давайте посмотрим на пример:

>>> 'Some string' or 1/0 
'Some string'
>>>

Поскольку 'Some string' оценивается как True, остальная часть or не оценивается, и ошибка деления на ноль не возникает.

Но если мы переключаем порядок, сначала оценивается 1/0 и возникает исключение:

>>> 1/0 or 'Some string'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 

Мы можем использовать это в качестве шаблона для проверки наличия ключа.

(k in d and 'blah')

делает то же самое, что и

if k in d:
    'blah'
else:
    False

Это уже возвращает правильный результат, если ключ существует, но мы хотим, чтобы он печатал «бу», когда его нет. Итак, берем результат и or с 'boo'

>>> False or 'boo'
'boo'
>>> 'blah' or 'boo'
'blah'
>>> 
avatar
Abdulkalek
12 февраля 2019 в 23:31
2

Вы можете использовать цикл for для перебора словаря и получения имени ключа, который вы хотите найти в словаре, после этого проверьте, существует он или нет, используя условие if:

dic = {'first' : 12, 'second' : 123}
for each in dic:
    if each == 'second': 
        print('the key exists and the corresponding value can be updated in the dictionary')
system123456
18 апреля 2019 в 18:38
0

проверьте код, потому что вывод для этого: it is exist и not exist

Jean-François Fabre♦
25 мая 2019 в 06:54
0

зачем вообще использовать словарь, если он предназначен для линейного поиска?

avatar
Charitoo
18 августа 2017 в 22:58
35

Использование тернарного оператора Python:

message = "blah" if 'key1' in my_dict else "booh"
print(message)
avatar
Siva Gnanam
26 апреля 2017 в 11:02
8

В словаре Python есть метод __contains__. Этот метод вернет True, если в словаре есть ключ, иначе вернет False.

 >>> temp = {}

 >>> help(temp.__contains__)

Help on built-in function __contains__:

__contains__(key, /) method of builtins.dict instance
    True if D has a key k, else False.
user1767754
14 ноября 2017 в 18:21
2

Звонить по номеру __contains__ напрямую - это очень плохая практика. Правильный способ сделать это - использовать оператор in, который представляет собой containment check, который вызывает функцию __contains__.

ron_g
8 января 2019 в 10:03
0

@ user1767754 Я использую foo = x['foo'] if x.__contains__('foo') else 'bar'. Есть идеи, как можно было бы использовать оператор in как часть этого выражения?

Ray Wu
13 июля 2019 в 17:11
1

foo = x['foo'] if 'foo' in x else 'bar'

avatar
mafonya
1 марта 2017 в 09:03
52

Словарь в Python имеет метод get ('key', default). Таким образом, вы можете просто установить значение по умолчанию, если ключа нет.

values = {...}
myValue = values.get('Key', None)
CodeBiker
24 мая 2021 в 21:19
0

Второй аргумент метода get является необязательным и по умолчанию имеет значение None, если не указан, поэтому values.get('Key', None) совпадает с values.get('Key').

avatar
Bishwas Mishra
21 декабря 2016 в 07:05
22

Способы получения результатов:

  • если your_dict.has_key (key) Удалено в Python 3
  • если введите your_dict
  • попробовать / исключить блок

Что лучше, зависит от 3 вещей:

  1. Словарь «обычно имеет ключ» или «обычно не имеет ключа».
  2. Собираетесь ли вы использовать такие условия, как if ... else ... elseif ... else?
  3. Насколько велик словарь?

Подробнее: http://paltman.com/try-except-performance-in-python-a-simple-test/

Использование try / block вместо 'in' или 'if':

try:
    my_dict_of_items[key_i_want_to_check]
except KeyError:
    # Do the operation you wanted to do for "key not present in dict".
else:
    # Do the operation you wanted to do with "key present in dict."
avatar
Wtower
29 мая 2015 в 11:06
74

Для получения дополнительной информации о скорости выполнения предложенных методов принятого ответа (10-метровые петли):

  • 'key' in mydict прошедшее время 1,07 сек
  • mydict.get('key') прошедшее время 1,84 сек
  • mydefaultdict['key'] прошедшее время 1,07 сек

Поэтому использование in или defaultdict рекомендуется вместо get.

Paul Rigor
15 июня 2017 в 16:59
10

полностью согласен с тем, что 1,84 с get равно <1,07 * 2 ;-P

avatar
HungryArthur
6 февраля 2014 в 16:08
40

А как насчет использования EAFP (проще просить прощения, чем разрешения):

try:
   blah = dict["mykey"]
   # key exists in dict
except KeyError:
   # key doesn't exist in dict

См. Другие сообщения SO:

Использование try vs if в python или

Проверка существования члена в Python

billrichards
19 августа 2014 в 20:07
17

Попробуйте / except может быть дороже, если вероятно, что ключ часто не существует. Из сообщения, на которое вы ссылались: «[I] если вы ожидаете, что 99% времени результат действительно будет содержать что-то повторяющееся, я бы использовал подход try / except. Это будет быстрее, если исключения действительно исключительные. Если результат None более чем в 50% случаев, то, вероятно, лучше использовать if. [...] [A] n if оператор всегда стоит вам, почти бесплатно настроить блок try / except. Но когда действительно возникает исключение, стоимость намного выше ". coderhelper.com/a/1835844/1094092

avatar
Mauricio Morales
19 мая 2013 в 18:12
17

Просто к вашему сведению, добавление Крису. B (лучший ответ):

d = defaultdict(int)

Тоже работает; причина в том, что вызов int() возвращает 0, что и делает defaultdict за кулисами (при построении словаря), отсюда и название «Заводская функция» в документации.

Chris B.
3 февраля 2014 в 19:35
2

Если вы создаете словарь счетчиков, вы должны использовать Counter (при условии Python 2.7). И я использовал defaultdict(lambda: 0) вместо defaultdict(int), потому что я думаю, что это более ясно, что происходит; читателю не нужно знать, что вы получите 0, если вызовете int() без аргументов. YMMV.

avatar
wan kenobi
9 мая 2013 в 10:17
21

Только Python 2: (а Python 2.7 уже поддерживает `in`)

вы можете использовать метод has_key():

if dict.has_key('xyz')==1:
    #update the value for the key
else:
    pass
Brad Koch
11 мая 2013 в 16:50
29

.has_key() был устаревшим; вы должны использовать in, как показано в других ответах.

ToolmakerSteve
16 декабря 2013 в 23:58
13

Кстати, я рекомендую прочитать ВСЕ существующие ответы на СТАРЫЙ вопрос, прежде чем отвечать на него. Этот ответ ничего не добавил, поскольку предложение уже существовало в ответе Майкла с '09. (Я не хочу препятствовать попыткам добавить что-то полезное в обсуждение. Продолжайте попытки.)

avatar
Michael Aaron Safyan
21 октября 2009 в 19:16
283

Вы можете проверить наличие ключа в словаре, используя в ключевом слове :

d = {'a': 1, 'b': 2}
'a' in d # <== evaluates to True
'c' in d # <== evaluates to False

Обычно для проверки существования ключа в словаре перед его изменением используется инициализация значения по умолчанию (например, если ваши значения являются списками, и вы хотите убедиться, что существует пустой список, для которого вы можете добавить при вставке первого значения для ключа). В подобных случаях вас может заинтересовать тип collections.defaultdict().

В старом коде вы также можете найти некоторые варианты использования has_key(), устаревшего метода проверки наличия ключей в словарях (вместо этого используйте key_name in dict_name).

avatar
David Berger
21 октября 2009 в 19:07
61

Я бы рекомендовал вместо этого использовать метод setdefault. Похоже, он сделает все, что вы хотите.

>>> d = {'foo':'bar'}
>>> q = d.setdefault('foo','baz') #Do not override the existing key
>>> print q #The value takes what was originally in the dictionary
bar
>>> print d
{'foo': 'bar'}
>>> r = d.setdefault('baz',18) #baz was never in the dictionary
>>> print r #Now r has the value supplied above
18
>>> print d #The dictionary's been updated
{'foo': 'bar', 'baz': 18}
hughdbrown
21 октября 2009 в 19:11
9

При чем здесь setdefault вопрос ОП?

David Berger
21 октября 2009 в 19:14
20

@hughdbrown "Я хотел проверить, существует ли ключ в словаре, прежде чем обновлять значение ключа". Иногда сообщения включают в себя код, который генерирует поток ответов на то, что не совсем исходная цель. Для достижения цели, указанной в первом предложении, setdefault является наиболее эффективным методом, даже если он не заменяет опубликованный образец кода.

avatar
Greg Hewgill
21 октября 2009 в 19:06
106

Код можно сократить до следующего:

if 'key1' in my_dict:
    ...

Однако это в лучшем случае косметическое улучшение. Почему вы считаете, что это не лучший способ?

Jason Baker
21 октября 2009 в 19:08
113

Это намного больше, чем косметическое улучшение. Время для поиска ключа с помощью этого метода составляет O (1), тогда как при вызове ключей создается список и будет O (n).

spectras
22 августа 2015 в 18:08
5

O (1) кажется не совсем правильным. Вы уверены, что это не что-то вроде O (log n)?

Leonora Tindall
28 октября 2015 в 00:18
15

Это сложность поиска по одному диктату, которая в среднем составляет O (1), а в худшем случае - O (n). .list () всегда будет O (n). wiki.python.org/moin/TimeComplexity

nurettin
9 декабря 2018 в 09:19
1

это также позволяет избежать дополнительного выделения. (важно для более быстрого создания узких петель)

avatar
Jason Baker
21 октября 2009 в 19:06
1649

Вам не нужно вызывать ключи:

if 'key1' in dict:
  print("blah")
else:
  print("boo")

Это будет намного быстрее, поскольку при этом используется хеширование словаря, а не линейный поиск, который выполнялся бы при вызове ключей.