Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Dictionaries and incrementing keys

Reply
Thread Tools

Dictionaries and incrementing keys

 
 
Steve Crook
Guest
Posts: n/a
 
      06-14-2011
Hi all,

I've always done key creation/incrementation using:

if key in dict:
dict[key] += 1
else:
dict[key] = 1

Today I spotted an alternative:

dict[key] = dict.get(key, 0) + 1

Whilst certainly more compact, I'd be interested in views on how
pythonesque this method is.
 
Reply With Quote
 
 
 
 
Peter Otten
Guest
Posts: n/a
 
      06-14-2011
Steve Crook wrote:

> I've always done key creation/incrementation using:
>
> if key in dict:
> dict[key] += 1
> else:
> dict[key] = 1


Your way is usually faster than

> dict[key] = dict.get(key, 0) + 1
>
> Whilst certainly more compact, I'd be interested in views on how
> pythonesque this method is.


You may also consider

http://docs.python.org/library/colle...ns.defaultdict
http://docs.python.org/library/colle...ctions.Counter
 
Reply With Quote
 
 
 
 
AlienBaby
Guest
Posts: n/a
 
      06-14-2011
On Jun 14, 12:16*pm, Peter Otten <__pete...@web.de> wrote:
> Steve Crook wrote:
> > I've always done key creation/incrementation using:

>
> > if key in dict:
> > * * dict[key] += 1
> > else:
> > * * dict[key] = 1

>
> Your way is usually faster than
>
> > dict[key] = dict.get(key, 0) + 1

>
> > Whilst certainly more compact, I'd be interested in views on how
> > pythonesque this method is.

>
> You may also consider
>
> http://docs.python.org/library/colle...ctions.Counter




How do those methods compare to the one I normally use;

try:
dict[key]+=1
except:
dict[key]=1

 
Reply With Quote
 
Steve Crook
Guest
Posts: n/a
 
      06-14-2011
On Tue, 14 Jun 2011 05:37:45 -0700 (PDT), AlienBaby wrote in
Message-Id: <078c5e9a-8fad-4d4c-b081->:

> How do those methods compare to the one I normally use;
>
> try:
> dict[key]+=1
> except:
> dict[key]=1


This is a lot slower in percentage terms. You should also qualify the
exception: except KeyError
 
Reply With Quote
 
Steve Crook
Guest
Posts: n/a
 
      06-14-2011
On Tue, 14 Jun 2011 13:16:47 +0200, Peter Otten wrote in
Message-Id: <it7fu4$rc5$>:

> Your way is usually faster than
>
>> dict[key] = dict.get(key, 0) + 1


Thanks Peter, ran it through Timeit and you're right. It's probably also
easier to read the conditional version, even if it is longer.

> You may also consider
>
> http://docs.python.org/library/colle...ns.defaultdict
> http://docs.python.org/library/colle...ctions.Counter


Useful functions, thanks again.
 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      06-14-2011
On Tue, 14 Jun 2011 10:57:44 +0000, Steve Crook wrote:

> Hi all,
>
> I've always done key creation/incrementation using:
>
> if key in dict:
> dict[key] += 1
> else:
> dict[key] = 1
>
> Today I spotted an alternative:
>
> dict[key] = dict.get(key, 0) + 1
>
> Whilst certainly more compact, I'd be interested in views on how
> pythonesque this method is.


Either version is perfectly fine. There's no reason to avoid either other
than personal preference.

The "if key in dict" version does up to three item lookups (first to see
if the key is in the dict, then to fetch the value, then to assign it),
the version with dict.get only does two.

If the key has an expensive hash function, the version using dict.get
will be much faster:

>>> key = ("abcdefgh"*10000, 5**30, frozenset(range(10000))) * 30
>>>
>>> from timeit import Timer
>>>
>>> t1 = Timer("""if key in d:

.... d[key] += 1
.... else:
.... d[key] = 1
.... """, "from __main__ import key; d = {key: 0}")
>>>
>>> t2 = Timer("d[key] = d.get(key, 0) + 1",

.... "from __main__ import key; d = {key: 0}")
>>>
>>> min(t1.repeat())

8.739075899124146
>>> min(t2.repeat())

6.425030946731567

but that will rarely be a problem in practice. For "normal" keys which
are small strings or ints, the "if key in dict" version will usually be
faster. Unless there are lots of missing keys, in which case the version
using dict.get may be faster.

Either way, the difference is unlikely to be significant except for the
tightest of tight loops.


--
Steven
 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      06-14-2011
On Tue, 14 Jun 2011 12:53:11 +0000, Steve Crook wrote:

> On Tue, 14 Jun 2011 05:37:45 -0700 (PDT), AlienBaby wrote in Message-Id:
> <078c5e9a-8fad-4d4c-b081->:
>
>> How do those methods compare to the one I normally use;
>>
>> try:
>> dict[key]+=1
>> except:
>> dict[key]=1

>
> This is a lot slower in percentage terms. You should also qualify the
> exception: except KeyError


Not necessarily. It depends on how often you have KeyError.

By my measurements, if the key is usually present, it is faster to use
try...except. Only if the key is frequently missing does it become faster
to test first.


--
Steven
 
Reply With Quote
 
Asen Bozhilov
Guest
Posts: n/a
 
      06-14-2011
Steve Crook wrote:

> Whilst certainly more compact, I'd be interested in views on how
> pythonesque this method is.


Instead of calling function you could use:

d = {}

d[key] = (key in d and d[key]) + 1

Regards.
 
Reply With Quote
 
Raymond Hettinger
Guest
Posts: n/a
 
      06-25-2011
On Jun 14, 12:57*pm, Steve Crook <st...@mixmin.net> wrote:
> Today I spotted an alternative:
>
> dict[key] = dict.get(key, 0) + 1
>
> Whilst certainly more compact, I'd be interested in views on how
> pythonesque this method is.


It is very pythonesque in the it was the traditional one way to do it
(also one of the fastest ways).

Now we have collections.Counter which simplifies the code to:

c = Counter()
...
c[key] += 1

For existing keys, it is as fast as a regular dictionary (because it
is a dict subclass and it does not override or extend either
__getitem__ or __setitem__). For new keys, it is a little slower
because it calls the __missing__ method which returns zero.

Raymond

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
updating dictionaries from/to dictionaries Brandon Python 12 08-15-2008 12:35 AM
Pickling dictionaries containing dictionaries: failing,recursion-style! lysdexia Python 6 12-02-2007 12:03 AM
Keys order in dictionaries Brainwashed Python 2 06-27-2003 08:53 AM
Re: Keys order in dictionaries W Isaac Carroll Python 0 06-27-2003 03:17 AM
Re: Keys order in dictionaries =?ISO-8859-1?Q?Gerhard_H=E4ring?= Python 0 06-26-2003 11:34 PM



Advertisments