473,396 Members | 2,034 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

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
Jul 18 '05 #1
16 3887
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
Jul 18 '05 #2
Dave,

On Wed, 09 Mar 2005 09:45:41 -0800, Dave Opstad <op****@batnet.com> 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
Jul 18 '05 #3
Maybe this can help:

value = d.get('x', lambda: bigscaryfunction())

Bearophile

Jul 18 '05 #4
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())
<function <lambda> at 0x40598e9c>
Dave

Jul 18 '05 #5
On 9 Mar 2005 10:05:21 -0800, be************@lycos.com
<be************@lycos.com> wrote:
Maybe this can help:

value = d.get('x', lambda: bigscaryfunction())

def test(): print 'gbye' .... d = {}
z = d.get('x', lambda: test())
z <function <lambda> at 0x008D6870>

So this seems to be merely an obfuscation of:
z = d.get('x', test)
z

<function test at 0x008D66B0>

I just wanted to ask, am I missing something?

Peace
Bill Mill
bill.mill at gmail.com
Jul 18 '05 #6
On 09 Mar 2005 18:13:01 GMT, F. Petitjean <li***********@news.proxad.net> 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
Jul 18 '05 #7
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
Jul 18 '05 #8
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
Jul 18 '05 #9
Bill Mill wrote:
On 9 Mar 2005 10:05:21 -0800, be************@lycos.com
<be************@lycos.com> wrote:
Maybe this can help:

value = d.get('x', lambda: bigscaryfunction())


def test(): print 'gbye' ...d = {}
z = d.get('x', lambda: test())
z <function <lambda> at 0x008D6870>

So this seems to be merely an obfuscation of:
z = d.get('x', test)
z

<function test at 0x008D66B0>

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
Jul 18 '05 #10
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
Jul 18 '05 #11
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)

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)

iD8DBQFCL4SfJd01MZaTXX0RAhrjAJ9hYiHBfdCdVOI2fR41A/zuLlSaZACfeLAs
Uhjj/Aiqa80532KKeD0dPYI=
=YVEi
-----END PGP SIGNATURE-----

Jul 18 '05 #12

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
Jul 18 '05 #13

"Skip Montanaro" <sk**@pobox.com> wrote in message
news:16***********************@montanaro.dyndns.or g...
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

Jul 18 '05 #14
Terry Reedy wrote:
"Skip Montanaro" <sk**@pobox.com> wrote in message
news:16***********************@montanaro.dyndns.or g...
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

Jul 18 '05 #15
On Fri, 11 Mar 2005 04:12:19 -0500, Steve Holden <st***@holdenweb.com> wrote:
Terry Reedy wrote:
"Skip Montanaro" <sk**@pobox.com> wrote in message
news:16***********************@montanaro.dyndns.or g...
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 NoneTrue >>>

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
Jul 18 '05 #16
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')"
1000000 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')"
1000000 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'"
1000000 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'"
1000000 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'"
1000000 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'"
100000 loops, best of 3: 2.71 usec per loop
Jul 18 '05 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: stuie... | last post by:
First off, I'm a newbie to PHP and server side scripting. I'm curious if there are any specific guidelines as to when one should use "GET" or "POST" in forms processing. I've had issues moreso...
10
by: Danny Anderson | last post by:
Hola! I have an array of shorts that represents a stream of data. This data is packed in tight, so certain elements may actually contain data for more than one variable. I am to decipher this...
8
by: NilsNilsson | last post by:
I wrote this: short s1 = 0; short s2 = 1; short s3 = s1 + s2; And gor this compile error message: Cannot implicitly convert type 'int' to 'short' What is wrong here?
3
by: Jingnan Si | last post by:
Hi, I am porting a old application from Asp, in the old code, I am using "Server.CreateObject("Scripting.FileSystemObject")" to get the file short name in 8.3 format, but I am wondering if there...
10
by: mg | last post by:
I want to enter characters in a TextBox in a WebForm, press a Button in the WebForm, and read the characters that were typed into the TextBox from within the Button_Click event handler. The main...
8
by: avsrk | last post by:
Hello Folks , General C data types question , more geared up towards embedded folks . I have a positive float quantity with a fractional part (one decimal point) which occupies 4 bytes ....
3
by: Matt Brown - identify | last post by:
Hello, I'm trying to figure out a method to look up by a range of dates, entries in a database. The format of the date in the database is "M\D \yyyy HH:MM:SS". What i need to do is take the...
9
by: magix | last post by:
If I have <form action="process.asp" method="get" name="form1"> .... .... <input TYPE=checkbox name=sports VALUE=Cricket> <input TYPE=checkbox name=sports VALUE=Swimming> <input...
6
by: Rainer Queck | last post by:
Hello NG, I am trying to adjust the column width of a DataGridView to the Text in its column header. To do this I am using the Graphics.MeasureString method. Unfortunatly I alway get a too...
7
by: Andrus | last post by:
How to get syntactically correct signature which compiles for code template grneration ? I tried code below but it creates syntactically incorrect signature. Andrus. using System; using...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.