<div dir="ltr"><div>[<span style="font-size:12.8px;font-weight:700;text-align:left;white-space:nowrap;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Steven D'Aprano</span><span style="font-size:12.8px;text-align:left;white-space:nowrap;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">]</span></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">In the case where all the inital counts are zero, the obvious API is to<span> <br></span></span><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">call the dict fromkeys method:</span><br style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial"><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"> Counter(dict.fromkeys(['a', 'b', 'ab'], 0))</span></blockquote><br style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial">Yes, I've discussed this, but since my replies have been miss addressed, it may have gotten lost.<br>I'll quote it below:<br><br>[Abe Dillon]<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"><font face="courier new, monospace">Counter(dict.fromkeys(keys, value))</font><span> </span>works just fine, but it feels wrong.<br>I'm using the copy-constructor because I know <font face="courier new, monospace">Counter</font> is a subclass of<span> </span><font face="courier new, monospace">dict</font><font face="arial, sans-serif">.<br></font><font face="arial, sans-serif">I'm using<span> </span></font><font face="courier new, monospace">fromkeys<span> </span></font><font face="arial, sans-serif">because I know how that class method works.<br></font>So why does the subclass lack functionality that the superclass has?<br>Because programmers wouldn't be able to wrap their heads around it?<br>I don't buy it. This feels like nanny-design trumping<span> </span><a href="https://en.wikipedia.org/wiki/SOLID" target="_blank" style="color:rgb(17,85,204)">SOLID design</a>.</blockquote><div><br><span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">[</span><span style="text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;font-weight:700;text-align:left;white-space:nowrap;background-color:rgb(255,255,255);float:none;display:inline">Steven D'Aprano</span><span style="text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;text-align:left;white-space:nowrap;background-color:rgb(255,255,255);float:none;display:inline">]</span><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">So what you're really asking for is a convenience method to bypass the<span> <br></span></span><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">need to create a temporary dict first</span></blockquote><div> </div><div>I'm not asking for anything all that new. Just that the existing .fromkeys inherited from dict not be disabled.<br><br><span style="font-size:small;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255);float:none;display:inline">[</span><span style="text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;font-weight:700;text-align:left;white-space:nowrap;background-color:rgb(255,255,255);float:none;display:inline">Steven D'Aprano</span><span style="text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;text-align:left;white-space:nowrap;background-color:rgb(255,255,255);float:none;display:inline">]</span><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Presumably the initial value will default to 0 rather than None, and<span> <br></span></span><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">take any integer value.</span></blockquote><br></div></div>Yes. I think that would make the most sense. 0 or 1. As long as it's documented it doesn't matter to me.<br><br><span style="font-size:small;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">[</span><span style="text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;font-weight:700;text-align:left;white-space:nowrap;float:none;display:inline">Steven D'Aprano</span><span style="text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;text-align:left;white-space:nowrap;float:none;display:inline">]</span><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Tim's point about duplicate keys is<span> </span></span><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">valid. Should it raise an exception, silently swallow duplicates, or<span> <br></span></span><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">count them?</span></blockquote><br>It should do exactly what dict.fromkeys does (except with a numeric default): ignore duplicates<div><br></div><div><span style="font-size:small;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">[</span><span style="text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;font-weight:700;text-align:left;white-space:nowrap;float:none;display:inline">Steven D'Aprano</span><span style="text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;text-align:left;white-space:nowrap;float:none;display:inline">]<br></span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">The dict constructors, both the standard dict() and dict.fromkeys(),<span> <br></span></span><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">silently swallow duplicates. As they should. But Counter() does not,<span> <br></span></span><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">and should not.</span></blockquote><div> </div>That's fine. I don't think that's confusing.<br><br><span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">[</span><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;font-weight:700;text-align:left;white-space:nowrap;float:none;display:inline">Steven D'Aprano</span><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;text-align:left;white-space:nowrap;float:none;display:inline">]</span><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">How about a fourth constructor? A fifth? A fiftith? How many<span> <br></span></span><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">constructors is too many before the class becomes unwieldy?</span></blockquote><div><br>I think this is a little overboard on the slippery-slope, no? I'm asking for a constructor that already exists, but was deliberately disabled.<br>As far as I can tell, the only people pointing out that others will complain are playing devil's advocate.</div><div>I can't tell if there are any people that actually believe that Counter.fromkeys should have a multiplier effect.<br>I wouldn't expect the campaign for the third type of constructor to get very far. Especially if Counter multiplication gets accepted.<br><br>[Tim]<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">I think the missing bit here is that there weren't any "constructor wars" for Counter...</span></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-aBn" tabindex="0" style="border-bottom:1px dashed rgb(204,204,204);font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><span class="gmail-aQJ" style="top: 2px; z-index: -1;">15 years later</span></span><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span> </span>you're jumping up & down about Counter.fromkeys() not being there, and that's why nobody much cares ;-)</span> </blockquote><br></div></div><div>I haven't been part of the conversation for 15 years, but most of the argument against the idea (yours especially) seem to focus on the prospect of a constructor war and imply that was the original motivation behind actively disabling the fromkeys method in Counters. I don't mean to give the impression that I'm fanatical about this. It really is a minor inconvenience. It doesn't irk me nearly as much as other minor things, like that the fact that all the functions in the heapq package begin with the redundant word 'heap'.<br><br>[Tim]<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-size:12.8px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Raymond may have a different judgment about that, though. I don't believe he reads python-ideas anymore</span></blockquote><div><br>He actually did reply a few comments back!<br>I think I'm having more fun chatting with people that I deeply respect than "jumping up and down". I'm sorry if I'm coming off as an asshole. We can kill this thread if everyone thinks I'm wasting their time. It doesn't look like anyone else shares my minor annoyance. Thanks for indulging me!</div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jun 29, 2018 at 9:37 PM, Steven D'Aprano <span dir="ltr"><<a href="mailto:steve@pearwood.info" target="_blank">steve@pearwood.info</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Fri, Jun 29, 2018 at 05:32:54PM -0700, Abe Dillon wrote:<br>
<br>
> Sure, but in Hettinger's own words <br>
</span>> <<a href="https://www.youtube.com/watch?v=HTLu2DFOdTg&t=24m46s" rel="noreferrer" target="_blank">https://www.youtube.com/<wbr>watch?v=HTLu2DFOdTg&t=24m46s</a>> "whenever you have a <br>
<span class="">> constructor war, everyone should get their wish". People that want a <br>
> counting constructor have that,<br>
> people that want the ability to initialize values don't have that.<br>
<br>
</span>*scratches head*<br>
<br>
I can initalise a Counter just fine.<br>
<br>
py> Counter({'a': 0, 'b': 0, 'ab': 2})<br>
Counter({'ab': 2, 'a': 0, 'b': 0})<br>
<br>
The supported API for setting initial values of a counter is to either <br>
count the supplied keys:<br>
<br>
Counter(['a', 'b', 'ab'])<br>
<br>
or supply initial counts in a dict:<br>
<br>
Counter({'a': 0, 'b': 0, 'ab': 2})<br>
<br>
In the case where all the inital counts are zero, the obvious API is to <br>
call the dict fromkeys method:<br>
<br>
Counter(dict.fromkeys(['a', 'b', 'ab'], 0))<br>
<br>
<br>
So what you're really asking for is a convenience method to bypass the <br>
need to create a temporary dict first:<br>
<br>
Counter.fromkeys(['a', 'b', 'ab'], 0)<br>
<br>
Presumably the initial value will default to 0 rather than None, and <br>
take any integer value.<br>
<br>
I'm sympathetic to the idea of this as a convenience, but I don't think <br>
its an obvious feature to have. Tim's point about duplicate keys is <br>
valid. Should it raise an exception, silently swallow duplicates, or <br>
count them?<br>
<br>
The dict constructors, both the standard dict() and dict.fromkeys(), <br>
silently swallow duplicates. As they should. But Counter() does not, <br>
and should not.<br>
<br>
There's a discrepency if Counter() doesn't and Counter.fromkeys() does, <br>
and it requires a value judgement to decide whether that discrepency is <br>
sufficiently unimportant.<br>
<br>
<br>
[...]<br>
<span class="">> Technically, there is no constructor for counting by X, but if enough <br>
> people really wanted that, I suppose a third constructor would be in order.<br>
<br>
</span>How about a fourth constructor? A fifth? A fiftith? How many <br>
constructors is too many before the class becomes unwieldy?<br>
<br>
Not every way you might count with a counter needs to be a constructor <br>
method. You can always just count:<br>
<br>
c = Counter()<br>
for key in keys:<br>
c[key] += X<br>
<br>
I think you make a *reasonable* case for Counter.fromkeys to silently <br>
ignore duplicates, as a convenience method for <br>
<br>
Counter(dict.fromkeys(keys, 0)<br>
<br>
but its not (in my opinion) a *compelling* argument. I think it comes <br>
down to the taste of the designer.<br>
<br>
You can always subclass it. Or even monkey-patch it.<br>
<br>
py> def fromkeys(cls, seq, value=0):<br>
... c = cls()<br>
... for key in seq:<br>
... c[key] = value<br>
... return c<br>
...<br>
py> from collections import Counter<br>
py> Counter.fromkeys = classmethod(fromkeys)<br>
py> Counter.fromkeys(['a', 'b', 'ab', 'a', 'b', 'c'])<br>
Counter({'a': 0, 'ab': 0, 'b': 0, 'c': 0})<br>
<br>
(Subclassing is safer :-)<br>
<span class="HOEnZb"><font color="#888888"><br>
<br>
<br>
-- <br>
Steve<br>
</font></span><div class="HOEnZb"><div class="h5">______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
</div></div></blockquote></div><br></div>