Lejlek
Lejlek

Reputation: 844

How to check for a key in a defaultdict without updating the dictionary (Python)?

I usually use the following idiom when working with a Python dictionary:

try:
    val = dct[key]
except KeyError:
    print key, " is not valid"

since for large dictionaries, the statement

if key in dct:
    # do something

is not very efficient (so I remember reading, but I've noticed it in practice as well)

Today I was working with a defaultdict and for a moment I forgot that a defaultdict will never give you a KeyError but instead will update the original dictionary.

How can I perform a lookup without updating the defaultdict? I really need to print an error so that the user can reenter the key.

Thank you!

UPDATE: Several posters suggested that my belief that if key in dct: is slow is false. I went back and checked the book in which I had read that is better to use try: except:. It is 2002's Python Cookbook, Recipe 1.4 by Alex Martelli, which can be found also online here: Add an entry to dictionary. Old memories are so unreliable! The recipe doesn't mention "slower" and it's not even using in but has_key. It simply says that try: except: is more Pythonic (at least the book version of the recipe). Thanks for the correction and the answers.

Upvotes: 25

Views: 28367

Answers (3)

dsz
dsz

Reputation: 5212

Let's not do double testing when we don't need to (at least in our code!)

val = dct.get(key, None)
if val is None:
    print key, " is not valid"

If None is a valid entry, then:

MISSING = object()
val = dct.get(key, MISSING)
if val is MISSING:
    print key, " is not valid"

Upvotes: 1

Fred Foo
Fred Foo

Reputation: 363757

How can I perform a lookup without updating the defaultdict?

With key in dct, i.e. explicitly.

If this is really too expensive for you (measure and you'll be sure), there are workarounds for specific situations. E.g., if your default value is 'ham' and in some situations you don't want to store (key, 'ham') in the defaultdict when key is not found, you can do

dct.get(key, 'ham')  # will return dct[key] or 'ham' but never stores anything

Upvotes: 28

Óscar López
Óscar López

Reputation: 236114

key in dct has to be fast, saying that is slow would be like saying that dct[key] is slow, and that must never be the case. Retrieving an element from a dictionary given its key and testing membership of a key have to be O(1) operations in any decent dictionary implementation, and it's easy to see how the membership operation could be implemented in terms of the access operation.

For your question with defaultdict, just use in. And there's no reason for avoiding the use of in in a normal dictionary.

Upvotes: 13

Related Questions