By Mohan Gulati


2009-10-21 19:05:09 8 Comments

I wanted to test if a key exists in a dictionary before updating the value for the key. I wrote the following code:

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

I think this is not the best way to accomplish this task. Is there a better way to test for a key in the dictionary?

16 comments

@Chris B. 2009-10-21 19:10:21

in is the intended way to test for the existence of a key in a dict.

d = dict()

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

If you wanted a default, you can always use dict.get():

d = dict()

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

... and if you wanted to always ensure a default value for any key you can use defaultdict from the collections module, like so:

from collections import defaultdict

d = defaultdict(int)

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

... but in general, the in keyword is the best way to do it.

@Jason Baker 2009-10-21 19:12:49

I usually just use get if I'm going to be pulling the item out of the dictionary anyway. No sense in using in and pulling the item out of the dictionary.

@Chris B. 2009-10-21 19:16:36

I fully agree. But if you only need to know if a key exists, or you need to distinguish between a case where the key is defined and a case where you are using a default, in is the best way of doing it.

@enkash 2015-01-28 05:54:11

Reference for this answer is at the python docs

@yaobin 2015-07-23 13:00:15

@enkash provided the reference for Python 3. Here is the reference for Python 2.7: dict and dict.get.

@Sebastien 2016-02-09 21:06:22

get is a bad test if the key is equivalent to "False", like 0 for example. Learned this the hard way :/

@Craig Hicks 2017-10-05 01:18:01

I can't agree that this a complete answer as it doesn't mention that 'try'-'except' will be the fastest when number of key fails is sufficiently small. See this answer below: stackoverflow.com/a/1602945/4376643

@hajef 2019-02-26 14:51:02

Is it just me or doesn't this "answer" match the question let alone answer it? I at least are more confused now and I can't even confirm the solution actually works.

@wan kenobi 2013-05-09 10:17:15

Python 2 only: (and python 2.7 supports in already)

you can use the has_key() method:

if dict.has_key('xyz')==1:
    #update the value for the key
else:
    pass

@Brad Koch 2013-05-11 16:50:42

.has_key() has been deprecated; you should use in as shown in other answers.

@ToolmakerSteve 2013-12-16 23:58:09

BTW, I recommend reading ALL existing answers to an OLD question, before answering it. This answer added nothing, since the suggestion already existed in Michael's answer, from '09. (I don't mean to discourage an attempt to add something useful to a discussion. Keep trying.)

@prosti 2019-05-23 20:14:37

Check if a given key already exists in a dictionary

To get the idea how to do that we first inspect what methods we can call on dictionary. Here are the methods:

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

The brutal method to check if the key already exists may be the get() method:

d.get("key")

The other two interesting methods items() and keys() sounds like too much of work. So let's examine if get() is the right method for us. We have our 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}

Printing shows the key we don't have will return None:

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

We may use that to get the info if the key is present or no. But consider this if we create a dict with a single key:None:

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

Leading that get() method is not reliable in case some values may be None. This story should have a happier ending. If we use the in comparator:

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

We get the correct results. We may examine the Python byte code:

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

This shows that in compare operator is not just more reliable but even faster than get().

@Abdulkalek 2019-02-12 23:31:31

You can use for loop to iterate over the dictionary and get the name of key you want to find in the dictionary, after that check if it exist or not using if condition:

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 2019-04-18 18:38:39

check over the code because the output for this is it is exist and not exist

@Jean-François Fabre 2019-05-25 06:54:36

why using a dictionary at all if this is to perform linear search?

@J. Antunes 2019-04-27 23:30:34

Sharing one more way of checking if a key exists using boolean operators.

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

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

This returns

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

Explanation

First you should know that in Python, 0, None, or objects with zero length evaluate to False. Everything else evaluates to True. Boolean operations are evaluated left to right and return the operand not True or False.

Let's see an example:

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

Since 'Some string' evaluates to True, the rest of the or is not evaluated and there is no division by zero error raised.

But if we switch the order 1/0 is evaluated first and raises an exception:

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

We can use this for pattern for checking if a key exists.

(k in d and 'blah')

does the same as

if k in d:
    'blah'
else:
    False

This already returns the correct result if the key exists, but we want it to print 'boo' when it doesn't. So, we take the result and or it with 'boo'

>>> False or 'boo'
'boo'
>>> 'blah' or 'boo'
'blah'
>>> 

@HungryArthur 2014-02-06 16:08:34

What about using EAFP (easier to ask forgiveness than permission):

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

See other SO posts:

Using try vs if in python or

Checking for member existence in Python

@billrichards 2014-08-19 20:07:17

Try/except may be more expensive if it's likely that the key often doesn't exist. From the post you referenced: "[I]f you expect that 99 % of the time result will actually contain something iterable, I'd use the try/except approach. It will be faster if exceptions really are exceptional. If result is None more than 50 % of the time, then using if is probably better.[...][A]n if statement always costs you, it's nearly free to set up a try/except block. But when an Exception actually occurs, the cost is much higher." stackoverflow.com/a/1835844/1094092

@mafonya 2017-03-01 09:03:28

Dictionary in python has a get('key', default) method. So you can just set a default value in case there is no key.

values = {...}
myValue = values.get('Key', None)

@Charitoo 2017-08-18 22:58:00

Using ternary operator:

message = "blah" if 'key1' in dict else "booh"
print(message)

@Siva Gnanam 2017-04-26 11:02:49

Python dictionary has the method called __contains__. This method will return True if the dictionary has the key else returns 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 2017-11-14 18:21:17

It is very bad practice to call __contains__ directly. The correct way of doing it, is to use in operator, which is the containment check that invokes the __contains__ function.

@ron g 2019-01-08 10:03:51

@user1767754 I'm using foo = x['foo'] if x.__contains__('foo') else 'bar'. Any ideas how would might use the in operator as part of this expression?

@Jason Baker 2009-10-21 19:06:30

You don't have to call keys:

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

That will be much faster as it uses the dictionary's hashing as opposed to doing a linear search, which calling keys would do.

@Mohan Gulati 2009-10-21 19:20:43

That is great. I was under the impression that it would internally still traverse the list of keys, but I see this works more like testing membership in a set.

@hughdbrown 2009-10-22 02:31:39

@Mohan Gulati: You understand that a dictionary is a hashtable of keys mapped to values, right? A hashing algorithm converts the key to an integer and the integer is used to find a location in the hash table that matches. en.wikipedia.org/wiki/Hash_table

@Charles Addis 2016-04-12 16:52:00

Still, it's good practice to call keys. The 'zen' of python basically gets at the fact that code should be explicit and self documenting. Calling keys() on a dict lets anybody reading the code know, "hey this is a dict" rather than a list or a tuple.

@ivan_bilan 2016-06-20 11:25:57

@Charles Addis, from experience working with around half a million keys you get at least 10x performance boost when writing "key in dict" instead of "key in dict.keys()". PEP and Zen also states that you should ignore them in case they are bad for your project.

@Charles Addis 2016-06-20 15:33:36

ivan_bilan -- I just ran my own benchtest on this... On half a million keys, if key in d1 took 0.17265701293945312 seconds. Calling if key in d1.keys() took 0.23871088027954102 -- this is the classic definition of a micro-optimization. Saving 0.07884883880615234 seconds is not a performance boost.

@Charles Addis 2016-06-20 15:34:28

@ivan_bilan And if 0.07884883880615234 matters so much for your project constraints, you probably should not be using python.

@Eli 2016-09-06 07:55:46

@CharlesAddis and if your project need to check existence of many keys for many times - IT SHOULD BE MATTER

@Charles Addis 2016-09-06 16:54:49

@eli I ran my test on half a million keys... and here we go, I'll run the EXACT SAME TEST ON A SET OF 50,000,000 keys... So let's see how big the difference is?!

@Charles Addis 2016-09-06 19:48:48

@Eli Just for you I've created a test you can run yourself. The results may astonish you. For dicts with ~50,000 keys, not calling keys() gives you .01 second computational benefit. For ~500,000 keys, not calling keys() gives you .1 second benefit. For ~5,000,000 keys, not calling keys() is .4 seconds faster, but for 50,000,000 keys CALLING keys() IS 3 SECONDS FASTER!

@Ukimiku 2016-10-19 20:15:19

Calling key() is 3 seconds faster? Are your 5,000,000 keys unique? Otherwise, there may be many hash values that collide, and the resolution of the collisions may take some time.

@Ukimiku 2016-10-25 20:20:13

Yes, thank you. Of course, you are right. Still, two unique keys might yield the same internal hash. So with 5,000,000 keys collisions seem more likely than with 5,000 keys. But that would depend on the implementation of the hashing, and I have not looked into the code for that.

@Surest Texas 2017-03-23 18:36:37

@Ukimiku (and others). This is a very helpful presentation from pycon 2010. As you will see, collisions happen very frequently even in small record-sets (<16 items). But python handles this automatically. Looking up an item in a dictionary is practically independent of its size: pyvideo.org/pycon-us-2010/the-mighty-dictionary-55.html

@Craig Hicks 2017-10-05 01:22:55

All this testing of 'if' and no testing of 'try','except KeyError'?

@Bishwas Mishra 2016-12-21 07:05:44

The ways in which you can get the results are:

Which is better is dependent on 3 things:

  1. Does the dictionary 'normally has the key' or 'normally does not have the key'.
  2. Do you intend to use conditions like if...else...elseif...else?
  3. How big is dictionary?

Read More: http://paltman.com/try-except-performance-in-python-a-simple-test/

Use of try/block instead of 'in' or '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."

@Jean Paul 2018-11-26 12:20:50

Good but need be actualized for python 3. I converted the script of the web page with 2to3, and saw that the without try syntax is always faster than the with try syntax, even in the case where the key is in the dict.

@Michael Aaron Safyan 2009-10-21 19:16:46

You can test for the presence of a key in a dictionary, using the in keyword:

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

A common use for checking the existence of a key in a dictionary before mutating it is to default-initialize the value (e.g. if your values are lists, for example, and you want to ensure that there is an empty list to which you can append when inserting the first value for a key). In cases such as those, you may find the collections.defaultdict() type to be of interest.

In older code, you may also find some uses of has_key(), a deprecated method for checking the existence of keys in dictionaries (just use key_name in dict_name, instead).

@Ido_f 2015-01-26 18:15:17

Wanted to share that (using Python 2.7) the run time of something I just wrote, basing heavily on dicts, was 363.235070 using "key in dict.keys()" and drastically went down to 0.260186 solely by removing the call for "keys()"

@Charles Addis 2016-06-21 21:33:09

@Ido_f please post your benchmarks, as my benchmarks almost no difference in 3.5 and 2.7

@Charles Addis 2016-06-21 21:34:16

@Ido_f I suspect it was something else in your program that was something else, but not actually key in dict.keys(). Try removing all code except for this check and see what your result is.

@Wtower 2015-05-29 11:06:44

For additional info on speed execution of the accepted answer's proposed methods (10m loops):

  • 'key' in mydict elapsed time 1.07 sec
  • mydict.get('key') elapsed time 1.84 sec
  • mydefaultdict['key'] elapsed time 1.07 sec

Therefore using in or defaultdict are recommended against get.

@scape 2015-06-11 23:02:27

get is in essence the combination of bullet points 1 and 3..

@Paul Rigor 2017-06-15 16:59:33

totally agree that get's 1.84s is < 1.07*2 ;-P

@Mauricio Morales 2013-05-19 18:12:35

Just an FYI adding to Chris. B (best answer):

d = defaultdict(int)

Works as well; the reason is that calling int() returns 0 which is what defaultdict does behind the scenes (when constructing a dictionary), hence the name "Factory Function" in the documentation.

@Chris B. 2014-02-03 19:35:29

If you're creating a dictionary of counts, you should be using Counter (assuming Python 2.7). And I used defaultdict(lambda: 0) instead of defaultdict(int) because I think it's clearer what's going on; the reader doesn't need to know you get 0 if you call int() without arguments. YMMV.

@David Berger 2009-10-21 19:07:28

I would recommend using the setdefault method instead. It sounds like it will do everything you want.

>>> 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 2009-10-21 19:11:11

What does setdefault have to do with the OP's question?

@David Berger 2009-10-21 19:14:14

@hughdbrown "I wanted to test if a key exists in a dictionary before updating the value for the key." Sometimes posts include code that generate a flurry of responses to something that's not quite the original goal. To accomplish the goal stated in the first sentence, setdefault is the most effective method, even though it's not a drop-in replacement for the sample code posted.

@Niels Bom 2012-07-24 13:07:37

This is the superior answer because it satisfies OP's goal instead of just giving the technically correct answer. See: nedbatchelder.com/blog/201207/…

@ToolmakerSteve 2013-12-16 23:42:26

+1 for an informative answer, that taught me something. However, whether it is the best solution depends on what the coder has in mind; e.g. the meaning of "before updating the value of the key". Maybe he's going to throw an exception if it is not present (== no permission to add new keys). Maybe its a dictionary of counts, and he's going to add 1 to the existing count, in which case `d[key] = d.get(key, 0) + 1' is the cleanest solution (as Chris shows, after your answer was written). (I only bother mentioning this, in case future readers come here, with different tasks in mind.)

@ToolmakerSteve 2013-12-16 23:46:11

@NielsBom ... IMHO setdefault is only the superior solution when an existing entry should not be overwritten. (An important case, but not the only reason to be testing existence of a key.)

@Niels Bom 2013-12-17 12:38:17

@ToolmakerSteve True. The problem here is that OP's question was not clear enough.

@Greg Hewgill 2009-10-21 19:06:40

You can shorten this:

if 'key1' in dict:
    ...

However, this is at best a cosmetic improvement. Why do you believe this is not the best way?

@Jason Baker 2009-10-21 19:08:19

This is much more than a cosmetic improvement. The time to find a key using this method is O(1) whereas calling keys would generate a list and be O(n).

@spectras 2015-08-22 18:08:54

The O(1) does not seem quite right. Are you sure it's not something like O(log n)?

@Leonora Tindall 2015-10-28 00:18:40

It's the complexity of a single dict lookup, which is on average O(1) and at worst O(n). .list() will always be O(n). wiki.python.org/moin/TimeComplexity

@nurettin 2018-12-09 09:19:28

this also avoids an extra allocation. (important for making tight loops a bit faster)

Related Questions

Sponsored Content

9 Answered Questions

[SOLVED] How to remove a key from a Python dictionary?

10 Answered Questions

[SOLVED] Iterating over dictionaries using 'for' loops

30 Answered Questions

[SOLVED] How do I check if a list is empty?

  • 2008-09-10 06:20:11
  • Ray Vega
  • 2217121 View
  • 3237 Score
  • 30 Answer
  • Tags:   python list

34 Answered Questions

[SOLVED] How do I sort a dictionary by value?

38 Answered Questions

[SOLVED] How do I check whether a file exists without exceptions?

15 Answered Questions

[SOLVED] Add new keys to a dictionary?

28 Answered Questions

[SOLVED] Finding the index of an item given a list containing it in Python

  • 2008-10-07 01:39:38
  • Eugene M
  • 3243994 View
  • 2674 Score
  • 28 Answer
  • Tags:   python list indexing

39 Answered Questions

[SOLVED] How to merge two dictionaries in a single expression?

27 Answered Questions

[SOLVED] What is the best way to iterate over a dictionary?

  • 2008-09-26 18:20:06
  • Jake Stewart
  • 1355262 View
  • 2253 Score
  • 27 Answer
  • Tags:   c# dictionary loops

11 Answered Questions

[SOLVED] Use of *args and **kwargs

  • 2010-08-03 08:28:07
  • MacPython
  • 809686 View
  • 1305 Score
  • 11 Answer
  • Tags:   python args kwargs

Sponsored Content