Is there a short-circuiting dictionary "get" method?

Michael Spencer mahs at telcopartners.com
Wed Mar 9 22:11:34 CET 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