MyTetra Share
Делитесь знаниями!
Check if a given key already exists in a dictionary
Время создания: 16.07.2018 10:48
Текстовые метки: python check key dictionary
Раздел: Python
Запись: Velonski/mytetra-database/master/base/1531720089iyj5v4ho8g/text.html на raw.githubusercontent.com

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?


python dictionary

shareimprove this question

edited May 2 '13 at 6:45


bluish

13k1590143

asked Oct 21 '09 at 19:05


Mohan Gulati

11.4k51720

20

Calling dict.keys() creates a list of keys, according to the documentation docs.python.org/2/library/stdtypes.html#dict.keys but I'd be surprised if this pattern wasn't optimised for, in a serious implementation, to translate to if 'key1' in dict:. – Evgeni Sergeev Aug 12 '13 at 8:51

5

So I finally found out why many of my Python scripts were so slow :) :(. That's because I've been using x in dict.keys() to check for keys. And that happened because the usual way to iterate over keys in Java is for (Type k : dict.keySet()), this habit causing for k in dict.keys() to feel more natural than for k in dict (which should still be fine in terms of performance?), but then checking keys becomes if k in dict.keys() too, which is a problem... – Evgeni Sergeev Aug 12 '13 at 8:58

4

@EvgeniSergeev if k in dict_: tests for presence of k in the KEYS of dict_, so you still don't need dict_.keys(). (This has bit me, as it reads to me like its testing for a value in dict. But it isn't.) – ToolmakerSteve Dec 16 '13 at 23:34

1

@ToolmakerSteve That's right, but not only do you not need it, it's not a good practice. – Evgeni Sergeev Dec 17 '13 at 1:51

15

Try "key in dict" – marcelosalloum Jun 26 '14 at 17:18

add a comment

19 Answers

active oldest votes

up vote

2201

down vote

accepted

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


d = dict()


for i in xrange(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 xrange(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(lambda: 0)


for i in xrange(100):

d[i % 10] += 1

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


shareimprove this answer

answered Oct 21 '09 at 19:10


Chris B.

41.3k1879113

50

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. – Jason Baker Oct 21 '09 at 19:12

45

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. – Chris B. Oct 21 '09 at 19:16

4

Reference for this answer is at the python docs – enkash Jan 28 '15 at 5:54

14

get is a bad test if the key is equivalent to "False", like 0 for example. Learned this the hard way :/ – Sebastien Feb 9 '16 at 21:06

2

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 – Craig Hicks Oct 5 '17 at 1:18

show 3 more comments

up vote

1076

down vote

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.


shareimprove this answer

edited May 23 '17 at 12:34


Community♦

11

answered Oct 21 '09 at 19:06


Jason Baker

99.6k102322479

5

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. – Mohan Gulati Oct 21 '09 at 19:20

34

@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 – hughdbrown Oct 22 '09 at 2:31

2

@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. – ivan_bilan Jun 20 '16 at 11:25

4

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 Jun 20 '16 at 15:33

2

@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! – Charles Addis Sep 6 '16 at 19:48

show 9 more comments

up vote

226

down vote

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).


shareimprove this answer

edited Jun 27 '16 at 23:12

answered Oct 21 '09 at 19:16


Michael Aaron Safyan

73.9k12108181

44

dict.has_key(key) has been deprecated in favor of key in dict – David Locke Oct 21 '09 at 19:28

4

Technically, has_key is deprecated for Python 2.x+ (not merely for 3.0+). That is, new code is recommended to not use it, even when writing in Python 2.x. (Because it is a feature known to be going away in future versions, and there is a perfectly good substitute to use instead.) What happens in 3.0 is that it is removed completely. – ToolmakerSteve Dec 16 '13 at 23:19

@ToolmakerSteve You are of course correct and I updated the answer to reflect that. :) – kqr Nov 6 '14 at 13:02

1

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()" – Ido_f Jan 26 '15 at 18:15

@Ido_f please post your benchmarks, as my benchmarks almost no difference in 3.5 and 2.7 – Charles Addis Jun 21 '16 at 21:33

show 1 more comment

up vote

73

down vote

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?


shareimprove this answer

answered Oct 21 '09 at 19:06


Greg Hewgill

632k1339881141

76

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). – Jason Baker Oct 21 '09 at 19:08

4

The O(1) does not seem quite right. Are you sure it's not something like O(log n)? – spectras Aug 22 '15 at 18:08

3

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 – Leo Tindall Oct 28 '15 at 0:18

add a comment

up vote

40

down vote

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}

shareimprove this answer

answered Oct 21 '09 at 19:07


David Berger

7,60332947

8

What does setdefault have to do with the OP's question? – hughdbrown Oct 21 '09 at 19:11

12

@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. – David Berger Oct 21 '09 at 19:14

3

This is the superior answer because it satisfies OP's goal instead of just giving the technically correct answer. See: nedbatchelder.com/blog/201207/… – Niels Bom Jul 24 '12 at 13:07

+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 Dec 16 '13 at 23:42

@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.) – ToolmakerSteve Dec 16 '13 at 23:46

show 1 more comment

up vote

34

down vote

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.


shareimprove this answer

answered May 29 '15 at 11:06


Wtower

9,29096155

4

get is in essence the combination of bullet points 1 and 3.. – scape Jun 11 '15 at 23:02

2

totally agree that get's 1.84s is < 1.07*2 ;-P – Paul Rigor Jun 15 '17 at 16:59

add a comment

up vote

17

down vote

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)

shareimprove this answer

edited Mar 23 at 18:51


Derlin

5,82621432

answered Mar 1 '17 at 9:03


mafonya

1,2841318

add a comment

up vote

15

down vote

For checking you can use has_key() method


if dict.has_key('key1'):

print "it is there"

If you want a value then you can use get() method


a = dict.get('key1', expeced_type)

If you want a tuple or list or dictionary or any string as a default value as return value, then use get() method


a = dict.get('key1', {}).get('key2', [])

shareimprove this answer

edited Jun 27 '16 at 6:41


abarisone

2,79692137

answered Sep 10 '15 at 18:37


Debabrata

423512

4

.get and has_key have already been suggested in answers years before yours, has_key has also been removed in python3 – Padraic Cunningham Dec 14 '15 at 19:58

add a comment

up vote

14

down vote

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


shareimprove this answer

edited May 10 at 19:22


Surest Texas

411419

answered Feb 6 '14 at 16:08


HungryArthur

470615

7

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 – billrichards Aug 19 '14 at 20:07

8

Instead of a bare catch I'd specify except KeyError here. – shuttle87 Jul 31 '15 at 14:40

add a comment

up vote

13

down vote

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.


shareimprove this answer

answered May 19 '13 at 18:12


Mauricio Morales

705810

1

(I gave you the +1, because Chris' defaultdict(lambda: 0) seemed obscure to me. saying "this is a dictionary of int's, so they start with the default value of an int, e.g. int() e.g. 0" I like.) – ToolmakerSteve Dec 17 '13 at 0:03

2

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. – Chris B. Feb 3 '14 at 19:35

add a comment

up vote

13

down vote

Using ternary operator:


message = "blah" if 'key1' in dict else "booh"

print(message)

shareimprove this answer

answered Aug 18 '17 at 22:58


Charitoo

702717

add a comment

up vote

11

down vote

You can use the has_key() method:


if dict.has_key('xyz')==1:

#update the value for the key

else:

pass

Or the dict.get method to set a default value if not found:


mydict = {"a": 5}


print mydict["a"] #prints 5

print mydict["b"] #Throws KeyError: 'b'


print mydict.get("a", 0) #prints 5

print mydict.get("b", 0) #prints 0

shareimprove this answer

edited Nov 7 '14 at 22:03


Eric Leschinski

77.9k35307257

answered May 9 '13 at 10:17


wan kenobi

16913

15

.has_key() has been deprecated; you should use in as shown in other answers. – Brad Koch May 11 '13 at 16:50

9

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.) – ToolmakerSteve Dec 16 '13 at 23:58

2

Wan Kenobi Please put @brad-kock comment on top. Indeed the answed has its own value but is not recommendable (not available atleast on Python 3.5.2). – Kuldeep Singh Dhaka Aug 20 '16 at 19:14

add a comment

up vote

11

down vote

The ways in which you can get the results are:


if your_dict.has_key(key) Removed in Python 3

if key in your_dict

try/except block

Which is better is dependent on 3 things:


Does the dictionary 'normally has the key' or 'normally does not have the key'.

Do you intend to use conditions like if...else...elseif...else?

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."

shareimprove this answer

answered Dec 21 '16 at 7:05


Bishwas Mishra

528416

add a comment

up vote

6

down vote

print dict.get('key1', 'blah')


Won't print boo for the values in the dict, but accomplishes the goal by printing the value of key1 to confirm it's existence instead.


shareimprove this answer

answered Jul 15 '15 at 18:55


gounc86

8314

add a comment

up vote

3

down vote

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.

shareimprove this answer

answered Apr 26 '17 at 11:02


Siva Gnanam

3642421

2

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. – user1767754 Nov 14 '17 at 18:21

add a comment

up vote

2

down vote

Well.. You will be familiar that searching a element's existence in a list or data means going through everything (at least for unordered list e.g dict.keys ).So Instead using Exception and Errors that arise normally we can avoid that complexity...


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

try:

needed=d[3]

print(needed)

except:

print("Key doesnt exist")

shareimprove this answer

answered Dec 9 '17 at 11:55


Seenivasan

5631613

add a comment

up vote

0

down vote

Easiest one is if you know which key(key name) is to look for:


# suppose your dictionary is

my_dict = {'foo': 1, 'bar': 2}

# check if a key is there

if 'key' in my_dict.keys(): # it will evaluates to true if that key is present otherwise false.

# do something

or you can also do simply as:


if 'key' in my_dict: # it will evaluates to true if that key is present otherwise false.

# do something

shareimprove this answer

answered Jun 13 '16 at 5:44


Tasneem Haider

4816

3

Repetition of the answer. This is not encouraged here. Please read through the already existing answers and ensure that you are not repeating the same answer. – Arun Thundyill Saseendran Aug 7 '17 at 10:49

add a comment

up vote

0

down vote

I use the try/except; if an exception is throwed, than the key aren't present at the dictionary. example:


st = 'sdhfjaks'

d = {}

try:

print d['st']

except Exception, e:

print 'Key not in the dictionary'

shareimprove this answer

answered Feb 7 at 22:02


Leonardo Maffei

6119

add a comment

up vote

-1

down vote

Why not just use the has_key() method.


a = {}

a.has_key('b') => #False


a['b'] = 8

a.has_key('b') => #True

shareimprove this answer

answered Jul 9 at 18:36


wmorris

103

This is a duplicate of other answers here. Please read the entire topic first before posting an answer. Also as mentioned in other answers: dict.has_key(key) has been deprecated in favor of key in dict. – nijm Jul 9 at 18:55

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования