Re: Is there a short-circuiting dictionary "get" method?
Bengt Richter wrote: > then there's always > >if 'x' in d: value = d['x'] >else: value = bsf() > > or > >try: value = d['x'] >except KeyError: value = bsf() > Its worth remembering that the first of those two suggestions is also faster than using get, so you aren't losing on speed if you write the code out in full: choose whichever seems clearest and uses the least contorted code. (The second is the fastest of all if the value is found, but a lot slower if the exception gets thrown.) C:\Python24\Lib>timeit.py -s "d={}" -s "for k in range(1000): d['x%s'%k]=k" "value = d.get('x45', 'notfound')" 100 loops, best of 3: 0.427 usec per loop C:\Python24\Lib>timeit.py -s "d={}" -s "for k in range(1000): d['x%s'%k]=k" "value = d.get('z45', 'notfound')" 100 loops, best of 3: 0.389 usec per loop C:\Python24\Lib>timeit.py -s "d={}" -s "for k in range(1000): d['x%s'%k]=k" "if 'x45' in d: value=d['x45']" "else: value='notfound'" 100 loops, best of 3: 0.259 usec per loop C:\Python24\Lib>timeit.py -s "d={}" -s "for k in range(1000): d['x%s'%k]=k" "if 'z45' in d: value=d['z45']" "else: value='notfound'" 100 loops, best of 3: 0.131 usec per loop C:\Python24\Lib>timeit.py -s "d={}" -s "for k in range(1000): d['x%s'%k]=k" "try: value=d['x45']" "except: value='notfound'" 100 loops, best of 3: 0.158 usec per loop C:\Python24\Lib>timeit.py -s "d={}" -s "for k in range(1000): d['x%s'%k]=k" "try: value=d['z45']" "except: value='notfound'" 10 loops, best of 3: 2.71 usec per loop -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
On Fri, 11 Mar 2005 04:12:19 -0500, Steve Holden <[EMAIL PROTECTED]> wrote: >Terry Reedy wrote: >> "Skip Montanaro" <[EMAIL PROTECTED]> wrote in message >> news:[EMAIL PROTECTED] >> >>> value = d.get('x') or bsf() >>> >>>Of course, this bsf() will get called if d['x'] evaluates to false, not >>>just >>>None, >> >> >> value = (d.get('x') is not None) or bsf() #?? >> >Unfortunately this will set value to True for all non-None values of >d['x']. Suppose d['x'] == 3: > > >>> 3 is not None >True > >>> > maybe (untested) value = ('x' in d and [d['x']] or [bsf()])[0] then there's always if 'x' in d: value = d['x'] else: value = bsf() or try: value = d['x'] except KeyError: value = bsf() Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
Terry Reedy wrote: "Skip Montanaro" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] value = d.get('x') or bsf() Of course, this bsf() will get called if d['x'] evaluates to false, not just None, value = (d.get('x') is not None) or bsf() #?? Unfortunately this will set value to True for all non-None values of d['x']. Suppose d['x'] == 3: >>> 3 is not None True >>> regards Steve -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
"Skip Montanaro" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] >value = d.get('x') or bsf() > > Of course, this bsf() will get called if d['x'] evaluates to false, not > just > None, value = (d.get('x') is not None) or bsf() #?? tjr -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
Dave> In this snippet: Dave> d = {'x': 1} Dave> value = d.get('x', bigscaryfunction()) Dave> the bigscaryfunction is always called, even though 'x' is a valid Dave> key. I sometimes use value = d.get('x') or bsf() Of course, this bsf() will get called if d['x'] evaluates to false, not just None, so it won't work in all situations. It may help often enough to be useful though. Skip -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
untested def my_getter(m, i, f): try: return m[i] except (KeyError, IndexError): return f() my_getter(d, 'x', bigscaryfunction) my_getter(d, 'y', lambda: scaryinlineexpresion) pgp04VRKFqQL1.pgp Description: PGP signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
Bill Mill wrote: On 9 Mar 2005 10:05:21 -0800, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote: Maybe this can help: value = d.get('x', lambda: bigscaryfunction()) def test(): print 'gbye' ... d = {} z = d.get('x', lambda: test()) z at 0x008D6870> So this seems to be merely an obfuscation of: z = d.get('x', test) z I just wanted to ask, am I missing something? Nope that looks right. See "Overuse of lambda" in http://www.python.org/moin/DubiousPython for discussion of exactly this mistake. STeVe -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
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... Well, if the dict only contains ints, here is a dirty hack (but don't use it instead of the try/except approach): class Littletinyproxy: def __int__(self): return bigscaryfunction() d = dict(x=1) value = int(d.get('x', Littletinyproxy())) Reinhold -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
F. Petitjean wrote: Le Wed, 09 Mar 2005 09:45:41 -0800, Dave Opstad a écrit : 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... def scary(): print "scary called" return 22 d = dict(x=1) d.get('x', lambda *a : scary()) # print 1 d.get('z', (lambda *a : scary())()) scary called 22 So you have to change the code at the point of call depending on whether the requested value is in the dict? ;) If you can get this to work I'm sure we can find other applications for such 'smart code' :-) Kent -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
On 09 Mar 2005 18:13:01 GMT, F. Petitjean <[EMAIL PROTECTED]> wrote: > Le Wed, 09 Mar 2005 09:45:41 -0800, Dave Opstad a écrit : > > 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... > def scary(): > print "scary called" > return 22 > > d = dict(x=1) > d.get('x', lambda *a : scary()) > > # print 1 > d.get('z', (lambda *a : scary())()) > scary called > 22 but: >>> d.get('x', (lambda *a: test())()) test called 1 So how is this different than d.get('x', test()) ? Peace Bill Mill bill.mill at gmail.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
On 9 Mar 2005 10:05:21 -0800, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote: > Maybe this can help: > > value = d.get('x', lambda: bigscaryfunction()) >>> def test(): print 'gbye' ... >>> d = {} >>> z = d.get('x', lambda: test()) >>> z at 0x008D6870> So this seems to be merely an obfuscation of: >>> z = d.get('x', test) >>> z I just wanted to ask, am I missing something? Peace Bill Mill bill.mill at gmail.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
Le Wed, 09 Mar 2005 09:45:41 -0800, Dave Opstad a écrit : > 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... def scary(): print "scary called" return 22 d = dict(x=1) d.get('x', lambda *a : scary()) # print 1 d.get('z', (lambda *a : scary())()) scary called 22 First (wrong) version : d.get('z', lambda *a : scary()) at 0x40598e9c> > > Dave -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
Maybe this can help: value = d.get('x', lambda: bigscaryfunction()) Bearophile -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
Dave, On Wed, 09 Mar 2005 09:45:41 -0800, Dave Opstad <[EMAIL PROTECTED]> 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... There is no short-circuit function like you're asking for, because it's impossible in python. To pass an argument to the 'get' function, python evaluates the bigscaryfunction before calling 'get'. (I believe this means that python doesn't have "lazy evaluation", but the language lawyers may shoot me down on that. Wikipedia seems to say that it means python doesn't have "delayed evaluation"). Here are two ways to do what you want: if 'x' in d: value = d['x'] else: value = bigscaryfunction() or: def sget(dict, key, func, *args): if key in dict: return key else: return func(*args) sget(d, 'x', bigscaryfunction) Both methods are untested, but should work with minor modifications. Peace Bill Mill bill.mill at gmail.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a short-circuiting dictionary "get" method?
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... try: value = d['x'] except KeyError: value = bigscaryfunction() get() is just a method, and arguments to methods are always evaluated before being passed to the method, so the short answer is "no, there is no 'version' of get() that will do what you want". -Peter -- http://mail.python.org/mailman/listinfo/python-list
Is there a short-circuiting dictionary "get" method?
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 -- http://mail.python.org/mailman/listinfo/python-list