On Tue, Apr 8, 2014 at 1:14 AM, Frank Millman <fr...@chagford.com> wrote: > > "Chris Angelico" <ros...@gmail.com> wrote in message > news:captjjmqfbt2xx+bdfnhz0gagordkhtpbzrr29duwn36girz...@mail.gmail.com... >> On Tue, Apr 8, 2014 at 2:02 PM, Josh English <joshua.r.engl...@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. -- https://mail.python.org/mailman/listinfo/python-list