This is half a new feature proposition, and half a doc update proposition.
I’m using the collections.Counter class, and I wanted to initialize a Counter with a series of keys being set to some integral value, let’s take 3 for example. I discovered that Counter.fromkeys is completely inactivated, and that workarounds using the Counter constructor are advised instead.
The reason at first glance is obvious : Counter relies on its values supporting addition, so a default value of None is a non-starter. So, I wondered, why not keep the method but make its value parameter required instead of optional ? In other words, why is Counter.fromkeys(iterable, v)
disabled even when I do provide a v
? Counter(iterable) * v
would be a workaround if Counter supported that arraying of operators, but it doesn’t (and I think that shouldn’t change).
New feature
I dug into the code, and quickly observed that a difficulty would be to respect Counter’s take on multiplicity : if a key is repeated in an iterable, Counter will cumulate its default value. So, a dumb implementation as this :
@classmethod
def fromkeys(cls, iterable, v): # notice v is not optional
super().fromkeys(iterable, v)
… would fail to take repetitions into account.
I put together a simple implem for that, which requires an adaptation on the C version of the _count_elements
helper function but the idea is there. It can be found here.
Doc update
However, I found that you already can do the version of this which doesn’t care about repetitions in the input iterable (which I don’t) in your code without modifying the stdlib, and without having to build one dict to be copied by the Counter. With this simple code : super(Counter, Counter).fromkeys(iterable, v)
.
My doc proposition is this : if the change to Counter.fromkeys is deemed not a good idea for various reasons (which I can understand, the conditions on the default value are a bit weird : it must support addition with 0 and results of that addition), how about adding that line to the doc, as a documented workaround ?
I suspect some number of people must have come there wondering why the fromkeys method doesn’t work, so giving them a workaround would be a fair tradeoff for taking the method away.
So, adding that super(Counter, Counter).fromkeys(iterable, v)
, and Counter(iterable)
if you don’t have a default value, and Counter(iterable.keys())
if it’s a mapping. And too bad if you want both repetition of the input iterable to matter and a non-1 default value, you’ll have to do that yourself, but at least we offer help for the other cases.
What do you all think ?