[Python-ideas] collections.Counter multiplication
Matthew Ruffalo
mmr15 at case.edu
Thu May 30 02:52:16 CEST 2013
On 05/29/2013 08:06 PM, Steven D'Aprano wrote:
> On 30/05/13 06:17, James K wrote:
>> It should work like this
>>
>> >>> from collections import Counter
>> >>> Counter({'a': 1, 'b': 2}) * 2 # scalar
>> Counter({'b': 4, 'a': 2})
>
> Under what circumstances would you do this?
>
> What is it about Counters that they should support multiplication when
> no other mapping type does?
Counters are different from other mapping types because they provide a
natural Python stdlib implementation of multisets -- the docs explicitly
state that "The Counter class is similar to bags or multisets in other
languages.". The class already has behavior that is different from other
mapping types: Counter.__init__ can also take an iterable of hashable
objects instead of another mapping, and Counter.update adds counts
instead of replacing them.
>
> For what it is worth, the above is trivially doable using dict
> comprehensions:
>
> py> from collections import Counter
> py> count = Counter({'a': 2, 'b': 3})
> py> Counter({k:v*2 for k,v in count.items()})
> Counter({'b': 6, 'a': 4})
>
>
>> >>> Counter({'a': 1, 'b': 2}) * Counter({'c': 1, 'b': 2}) #
>> multiplies
>> matching keys
>> Counter({'b': 4})
>>
>>
>> This is intuitive behavior and therefore should be added.
>
> Not to me it isn't. I cannot guess what purpose this would hold, or
> why you would want to do this.
>
>
>> I am unsure about
>> division as dividing by a non-existing key would be a division by 0,
>> although division by a scalar is straightforward.
>
> Oh, so now you're proposing division as well? I presume you would want
> to support both / and // division, since they're both equally intuitive:
>
> Counter({'a': 10})/3
> => Counter({'a': 3.3333333333333333})
>
> Counter({'a': 10})//Counter({'a': 3, 'b': 4})
> => Counter({'a': 3, 'b': 0})
>
> What about other operations, like ** & | ^ >> << ? Is it your proposal
> that Counters should support every operation that ints support?
>
Counters already support & and | for multiset intersection and union.
From http://docs.python.org/3/library/collections.html :
"""
>>>c = Counter(a=3, b=1)
>>>d = Counter(a=1, b=2)
>>>c + d # add two counters together: c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>>c - d # subtract (keeping only positive counts)
Counter({'a': 2})
>>>c & d # intersection: min(c[x], d[x])
Counter({'a': 1, 'b': 1})
>>>c | d # union: max(c[x], d[x])
Counter({'a': 3, 'b': 2})
"""
The rationale for supporting multiplication by a scalar makes some sense
when using Counters as multisets; multiplying by a another Counter is
questionable.
MMR...
More information about the Python-ideas
mailing list