Dictionaries and incrementing keys

Discussion in 'Python' started by Steve Crook, Jun 14, 2011.

  1. Steve Crook

    Steve Crook Guest

    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.
    Steve Crook, Jun 14, 2011
    #1
    1. Advertising

  2. Steve Crook

    Peter Otten Guest

    Peter Otten, Jun 14, 2011
    #2
    1. Advertising

  3. Steve Crook

    AlienBaby Guest

    On Jun 14, 12:16 pm, Peter Otten <> 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/coll.../library/collections.html#collections.Counter




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

    try:
    dict[key]+=1
    except:
    dict[key]=1
    AlienBaby, Jun 14, 2011
    #3
  4. Steve Crook

    Steve Crook Guest

    On Tue, 14 Jun 2011 05:37:45 -0700 (PDT), AlienBaby wrote in
    Message-Id: <>:

    > 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
    Steve Crook, Jun 14, 2011
    #4
  5. Steve Crook

    Steve Crook Guest

    Steve Crook, Jun 14, 2011
    #5
  6. 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
    Steven D'Aprano, Jun 14, 2011
    #6
  7. 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:
    > <>:
    >
    >> 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
    Steven D'Aprano, Jun 14, 2011
    #7
  8. 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.
    Asen Bozhilov, Jun 14, 2011
    #8
  9. On Jun 14, 12:57 pm, Steve Crook <> 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
    Raymond Hettinger, Jun 25, 2011
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Brainwashed

    Keys order in dictionaries

    Brainwashed, Jun 27, 2003, in forum: Python
    Replies:
    2
    Views:
    757
    Duncan Booth
    Jun 27, 2003
  2. =?ISO-8859-1?Q?Gerhard_H=E4ring?=

    Re: Keys order in dictionaries

    =?ISO-8859-1?Q?Gerhard_H=E4ring?=, Jun 27, 2003, in forum: Python
    Replies:
    0
    Views:
    669
    =?ISO-8859-1?Q?Gerhard_H=E4ring?=
    Jun 27, 2003
  3. W Isaac Carroll

    Re: Keys order in dictionaries

    W Isaac Carroll, Jun 27, 2003, in forum: Python
    Replies:
    0
    Views:
    626
    W Isaac Carroll
    Jun 27, 2003
  4. lysdexia
    Replies:
    6
    Views:
    479
    John Machin
    Dec 2, 2007
  5. Brandon
    Replies:
    12
    Views:
    479
    Brandon
    Aug 15, 2008
Loading...

Share This Page