Keeping track of things with dictionaries

Ian Kelly ian.g.kelly at gmail.com
Tue Apr 8 03:53:33 EDT 2014


On Tue, Apr 8, 2014 at 1:14 AM, Frank Millman <frank at chagford.com> wrote:
>
> "Chris Angelico" <rosuav at gmail.com> wrote in message
> news:CAPTjJmqFBt2XX+BDfNHz0gaGOrDkhtpBzrR29DUWN36girzcSw at mail.gmail.com...
>> On Tue, Apr 8, 2014 at 2:02 PM, Josh English <Joshua.R.English at gmail.com>
>> wrote:
>>>
>>> Would dict.setdefault() solve this problem? Is there any advantage to
>>> defaultdict over setdefault()
>>
>> That depends on whether calling Brand() unnecessarily is a problem.
>> Using setdefault() is handy when you're working with a simple list or
>> something, but if calling Brand() is costly, or (worse) if it has side
>> effects that you don't want, then you need to use a defaultdict.
>>
>
> It appears that when you use 'setdefault', the default is always evaluated,
> even if the key exists.
>
>>>> def get_value(val):
> ...   print('getting value', val)
> ...   return val*2
> ...
>>>> my_dict = {}
>>>> my_dict.setdefault('a', get_value('xyz'))
> getting value xyz
> 'xyzxyz'
>>>> my_dict.setdefault('a', get_value('abc'))
> getting value abc
> 'xyzxyz'
>>>> my_dict
> {'a': 'xyzxyz'}
>>>>
>
> It seems odd. Is there a situation where this behaviour is useful?

No.  The default argument is evaluated because it must be evaluated
before it can be passed into the method, just like any other function
argument in Python.  So why doesn't it take a callable instead of a
value for its second argument?  At a guess, because the method was
probably added for efficiency, and the function call overhead might
easily be slower than just doing a separate getitem and setitem.

The reason setdefault exists I think is primarily because it was added
before defaultdict.  The contributors at SO can't seem to come up with
any particularly good use cases either:

http://stackoverflow.com/questions/3483520/use-cases-for-the-setdefault-dict-method

One thing I will note as a disadvantage of defaultdict is that
sometimes you only want the default value behavior while you're
initially building the dict, and then you just want a normal dict with
KeyErrors from then on.  defaultdict doesn't do that; once
constructed, it will always be a defaultdict.  You can copy the data
into a normal dict using the dict() constructor, but this feels dirty
to me.



More information about the Python-list mailing list