<dict>.setdefault()

Discussion in 'Python' started by Tino Lange, Jul 31, 2003.

  1. Tino Lange

    Tino Lange Guest

    Hi!

    I just realized that <dict>.setdefault *always* executes the second
    argument - even if it's not necessary, because the requested item in
    the first argument exists.

    This is not what I expected - why evaluate the second argument if it's
    not needed? Also this can lead to side-effects!

    Example:

    >>> a = {}
    >>> b = {}
    >>> a.setdefault(1,b.setdefault(1,1))

    1

    '1' didn't exist in a - so I expect 'b.setdefault(1,1)' to be
    evaluated. Great.

    >>> a.setdefault(1,b.setdefault(2,1))

    1

    '1' existed, so it's not necessary to evaluate 'b.setdefault(2,1)'.
    But:

    >>> b

    {2: 1, 1: 1}

    .... shows that it was executed!

    So it's not equivalent to:

    if 1not in a:
    b.setdefault(2,1)

    Is this really by design? If there's a complicated, expensive to
    calculate/build 2nd argument (maybe a function call) then it's also
    quite ineffective to evaluate it just to throw away...

    Thanks!

    Tino
     
    Tino Lange, Jul 31, 2003
    #1
    1. Advertising

  2. Tino Lange a écrit :
    > I just realized that <dict>.setdefault *always* executes the second
    > argument - even if it's not necessary, because the requested item in
    > the first argument exists.


    Since setdefault is a method, this is coherent with Python's standard
    behaviour: method and function arguments are always evaluated before the
    method is called.

    --
    Alexandre Fayolle
    LOGILAB, Paris (France).
    http://www.logilab.com http://www.logilab.fr http://www.logilab.org
    Développement logiciel avancé - Intelligence Artificielle - Formations
     
    Alexandre Fayolle, Jul 31, 2003
    #2
    1. Advertising

  3. Tino Lange

    Tino Lange Guest

    On Thu, 31 Jul 2003 16:54:46 +0000 (UTC), Alexandre Fayolle
    <> wrote:

    >> I just realized that <dict>.setdefault *always* executes the second
    >> argument - even if it's not necessary, because the requested item in
    >> the first argument exists.


    > method and function arguments are always evaluated before the
    >method is called.


    Yep. You're right. Of course it's like that.
    Anyway - that's not what I expected in the first thought.

    It shows that less code is not always the best code...

    Thanks!

    Tino
     
    Tino Lange, Jul 31, 2003
    #3
  4. Tino Lange

    Tino Lange Guest

    On 31 Jul 2003 18:01:51 +0100, (John J. Lee) wrote:

    >Because that's the way Python always does function calls?


    Of course. From the consistency point of view... perfectly right!
    (I thought that maybe because these are very special low-level methods
    for built-in types, it might be different....)

    >Don't, then. :) Use key in dict, or dict.has_key(key).


    or the C-like style:
    >>> a[3] = a.get(1) or b.setdefault(4,1)


    Thanks!

    Tino
     
    Tino Lange, Jul 31, 2003
    #4
  5. Tino Lange wrote:

    > I just realized that <dict>.setdefault *always* executes the second
    > argument - even if it's not necessary, because the requested item in
    > the first argument exists.
    >
    > This is not what I expected - why evaluate the second argument if it's
    > not needed? Also this can lead to side-effects!


    Because Python doesn't have macros or special forms that look like
    functions. If you see something that looks like a function, it
    evaluates all arguments before it calls the function. Always. Changing
    this would cause confusion, not resolve it.

    --
    Erik Max Francis && && http://www.alcyone.com/max/
    __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
    / \ There's a reason why we / Keep chasing morning
    \__/ Sandra St. Victor
     
    Erik Max Francis, Jul 31, 2003
    #5
  6. Quoth Tino Lange:
    > On 31 Jul 2003 18:01:51 +0100, (John J. Lee) wrote:

    [...]
    > >Don't, then. :) Use key in dict, or dict.has_key(key).

    >
    > or the C-like style:
    > >>> a[3] = a.get(1) or b.setdefault(4,1)


    Be careful doing that -- it relies on all possible values for a[1]
    being true. Consider:

    >>> a = {1: 0}
    >>> b = {}
    >>> a[3] = a.get(1) or b.setdefault(4, 1)
    >>> a

    {1: 0, 3: 1}
    >>> b

    {4: 1}

    --
    Steven Taschuk o- @
    7O )
    " (
     
    Steven Taschuk, Aug 1, 2003
    #6
    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. Leo Breebaart

    Delayed evaluation and setdefault()

    Leo Breebaart, Jan 19, 2004, in forum: Python
    Replies:
    7
    Views:
    432
  2. Cole Tuininga

    setdefault threadsafe?

    Cole Tuininga, Aug 24, 2004, in forum: Python
    Replies:
    0
    Views:
    370
    Cole Tuininga
    Aug 24, 2004
  3. Ron Garret

    Setdefault bypasses __setitem__

    Ron Garret, Oct 13, 2005, in forum: Python
    Replies:
    9
    Views:
    472
    Fredrik Lundh
    Oct 14, 2005
  4. rantingrick

    [Feature Request] dict.setdefault()

    rantingrick, Apr 11, 2011, in forum: Python
    Replies:
    11
    Views:
    378
    Thomas Rachel
    Apr 25, 2011
  5. pete McEvoy

    setdefault behaviour question

    pete McEvoy, May 19, 2012, in forum: Python
    Replies:
    1
    Views:
    355
    pete McEvoy
    May 19, 2012
Loading...

Share This Page