Is there a short-circuiting dictionary "get" method?
Michael Spencer
mahs at telcopartners.com
Wed Mar 9 16:11:34 EST 2005
Dave Opstad wrote:
> In this snippet:
>
> d = {'x': 1}
> value = d.get('x', bigscaryfunction())
>
> the bigscaryfunction is always called, even though 'x' is a valid key.
> Is there a "short-circuit" version of get that doesn't evaluate the
> second argument if the first is a valid key? For now I'll code around
> it, but this behavior surprised me a bit...
>
> Dave
If (and this is a big if) you know that the dictionary contains no values that
evaluate to boolean false, then you can use the short-circuiting 'or' operator:
>>> def bigscaryfunction():
... print "scary"
...
>>> d= globals()
>>> d.get("key") or bigscaryfunction()
scary
>>> d.get("__name__") or bigscaryfunction()
'LazyDictget'
>>>
Alternatively, you can just write your own getter function:
>>> def lazyget(dict_, key, default):
... if key in dict_:
... return dict_[key]
... else:
... return default()
...
>>> lazyget(d,"key",bigscaryfunction)
scary
>>> lazyget(d,"__name__",bigscaryfunction)
'LazyDictget'
>>>
The optimal choice of whether to "look before you leap" i.e., "if key in dict_"
or simply catch KeyError, depends on the ratio of hits to misses. Google will
turn up some experimental data on this, but, I seem to recall that if more than
10% attempts are misses, then LBYL is faster, because raising the exception is slow
Michael
More information about the Python-list
mailing list