Modification of collections.Counter/Dictionary (to not store negative values)

I found the Counter datatype from the collections module and it is almost perfect for my usecase. However I would like to implement a "simple" modification so it does not accept negative values and raises an error instead.

from collections import Counter
c = Counter({"a": 1})
c.update({"a": -2})    # this should raise an error since c[a] = -1

d = Counter({"b": -5})    # this should raise an error aswell

Of course I could just write a function to check all values and call it after each interaction with the counter, but this sounds like a bad idea to me.

If this is too much of a "do not ask others for code" question i apologize. I would be quite happy about specific info about the implementation of "Counter" aswell.

EDIT: I think an example with a standard dictionary would be perfectly fine. So the question would boil down to "How can i make a dictionary which raises an error if a value is a negative integer?"


I'd do this by just subclassing dict rather than Counter, since it gives you fewer methods to override:

>>> class PositiveDict(dict):
...     __slots__ = ()
...     def __init__(self, *args, **kwargs):
...         super().__init__(*args, **kwargs)
...         if any(v < 0 for v in self.values()):
...             raise ValueError("no negatives allowed!")
...     def __getitem__(self, key):
...         return self.get(key, 0)
...     def __setitem__(self, key, val):
...         if val < 0:
...             raise ValueError("no negatives allowed!")
...         super().__setitem__(key, val)
...     def update(self, other):
...         if any(v < 0 for v in other.values()):
...             raise ValueError("no negatives allowed!")
...         super().update(other)
...
>>> d = PositiveDict({"a": 1})
>>> d["a"] -= 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 11, in __setitem__
ValueError: no negatives allowed!
>>> d.update({"a": -2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 15, in update
ValueError: no negatives allowed!
>>> d["a"] += 1
>>> d["a"]
2
>>> d["b"]
0

Note that the __getitem__ implementation gives you the default value that you wanted from Counter. Everything else works by checking for a negative either before or after calling the super() version of the method.