Just a little improvement: you don't need the l local variable, you can just 
call append:

d.setdefault(foo, []).append(bar)

And correspondingly:
d[foo].append(bar)

> On 2 Nov 2018, at 17:52, Chris Barker via Python-ideas 
> <python-ideas@python.org> wrote:
> 
>> On Thu, Nov 1, 2018 at 8:34 PM, Steven D'Aprano <st...@pearwood.info> wrote:
>> The bottom line is, if I understand your proposal, the functionality 
>> already exists. All you need do is subclass dict and give it a 
>> __missing__ method which does what you want.
> 
> or subclass dict and give it a "setdefault_call") method :-)
> 
> But as I think Guido wasa pointing out, the real difference here is that 
> DefaultDict, or any other subclass, is specifying what the default callable 
> is for the entire dict, rather than at time of use. Personally, I'm pretty 
> sure I"ve only used one default for any given dict, but I can imaige the are 
> use cases for having different defaults for the same dict depending on 
> context.
> 
> As for the OP's justification:
> 
> """
> If it's not clear, the purpose is to eliminate the overhead of creating an 
> empty list or similar in situations like this:
> 
> d = {}
> for i in range(1000000):  # some large loop
>      l = d.setdefault(somekey, [])
>      l.append(somevalue)
> 
> # instead...
> 
> for i in range(1000000):
>     l = d.setdefault_call(somekey, list)
>     l.append(somevalue)
> 
> """
> 
> I presume the point is that in the first case, somekey might be often the 
> same, and setdefault requires creating an actual empty list even if  the key 
> is alredy there. whereas case 2 will only create the empty list if the key is 
> not there. doing some timing with defaultdict:
> 
> In [19]: def setdefault():
>     ...:     d = {}
>     ...:     somekey = 5
>     ...:     for i in range(1000000):  # some large loop
>     ...:         l = d.setdefault(somekey, [])
>     ...:         l.append(i)
>     ...:     return d
> 
> In [20]: def default_dict():
>     ...:     d = defaultdict(list)
>     ...:     somekey = 5
>     ...:     for i in range(1000000):  # some large loop
>     ...:         l = d[somekey]
>     ...:         l.append(i)
>     ...:     return d
> 
> In [21]: % timeit setdefault()
> 185 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
> 
> In [22]: % timeit default_dict()
> 128 ms ± 1.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
> 
> so yeah, it's a little more performant, and I suppose if you were using a 
> more expensive constructor, it would make a lot more difference. But then, 
> how much is it likely to matter in a real use cases -- this was 1 million 
> calls for one key and you got a 50% speed up -- is that common?
> 
> So it seems this would give us slightly better performance than .setdefault() 
> for the use cases where you are using more than one default for a given dict.
> 
> BTW:
> 
> +1 for a mention of defaultdict in the dict.setdefault docs -- you can't do 
> everything with defaultdict that you can with setdefault, but it is a very 
> common use case.
> 
> -CHB
> 
> -- 
> 
> Christopher Barker, Ph.D.
> Oceanographer
> 
> Emergency Response Division
> NOAA/NOS/OR&R            (206) 526-6959   voice
> 7600 Sand Point Way NE   (206) 526-6329   fax
> Seattle, WA  98115       (206) 526-6317   main reception
> 
> chris.bar...@noaa.gov
> _______________________________________________
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to