On 16/04/2018 06:07, Tim Peters wrote: > [Peter Norvig] >> For most types that implement __add__, `x + x` is equal to `2 * x`. >> >> That is true for all numbers, list, tuple, str, timedelta, etc. -- but not >> for collections.Counter. I can add two Counters, but I can't multiply one >> by a scalar. That seems like an oversight. >> >> ... >> Here's an implementation: >> >> def __mul__(self, scalar): >> "Multiply each entry by a scalar." >> result = Counter() >> for key in self: >> result[key] = self[key] * scalar >> return result >> >> def __rmul__(self, scalar): >> "Multiply each entry by a scalar." >> result = Counter() >> for key in self: >> result[key] = scalar * self[key] >> return result > > Adding Counter * integer doesn't bother me a bit, but the definition > of what that should compute isn't obvious. In particular, that > implementation doesn't preserve that `x+x == 2*x` if x has any > negative values: > >>>> x = Counter(a=-1) >>>> x > Counter({'a': -1}) >>>> x+x > Counter() > > It would be strange if x+x != 2*x, and if x*-1 != -x: > >>>> y = Counter(a=1) >>>> y > Counter({'a': 1}) >>>> -y > Counter() > > Etc. > > Then again, it's already the case that, e.g., x-y isn't always the > same as x + -y: > >>>> x = Counter(a=1) >>>> y = Counter(a=2) >>>> x - y > Counter() >>>> x + -y > Counter({'a': 1}) > > So screw obvious formal identities ;-) > > I'm not clear on why "+" and "-" discard keys with values <= 0 to > begin with. For "-" it's natural enough viewing "-" as being multiset > difference, but for "+"? That's just made up ;-) > > In any case, despite the oddities, I think your implementation would > be least surprising overall (ignore the sign of the resulting values). > At least for Counters that actually make sense as multisets (have no > values <= 0), and for a positive integer multiplier `n > 0`, it does > preserve that `x*n` = `x + x + ... + x` (with `n` instances of `x`). > _______________________________________________ > Python-ideas mailing list > Python-ideas@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ >
Wouldn't it make sense to have the current counter behaviour, (negative counts not allowed), and also a counter that did allow negative values (my bank doesn't seem to have a problem with my balance being able to go below negative), and possibly at the same time a counter class that allowed fractional counts? Then: >>>> x = Counter(a=1) >>>> y = Counter(a=2) >>>> x - y > Counter() >>>> x + -y > Counter({'a': 1}) BUT: >>>> x = Counter(a=1, allow_negative=True) >>>> y = Counter(a=2, allow_negative=True) >>>> x - y > Counter({'a': 1}) >>>> x + -y > Counter({'a': 1}) Likewise for a Counter that was allowed to be fractional the result of some_counter / scalar would have (potentially) fractional results and one that did not would give floor results. -- Steve (Gadget) Barnes Any opinions in this message are my personal opinions and do not reflect those of my employer. --- This email has been checked for viruses by AVG. http://www.avg.com _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/