Hi, I need to store values for metrics and return the average for some and the sum for the rest. Thus, I thought I could extend collections.Counter class by returning averages for some keys.
My class modifies the update() to increment a counter and the __getitem__ to perform the calculation. But, I get RuntimeError: maximum recursion depth exceeded as I access an attribute inside __getitem__. Does anyone has an idea how I can achieve this? Example:: In [7]: metrics = {'f':6, 'g':1} In [8]: avg_metrics = ['f'] In [9]: a = CounterExt(avg_metrics=avg_metrics) In [10]: a.update(metrics) In [11]: a Out[11]: CounterExt({'f': 6, 'g': 1}) In [12]: a.update(metrics) In [13]: a Out[13]: CounterExt({'f': 12, 'g': 2}) In [14]: a['f'] ......... RuntimeError: maximum recursion depth exceeded Code:: from collections import Counter from collections.abc import Mapping class CounterExt(Counter): def __init__(self, iterable=None, avg_metrics=None, **kwds): self._counter = 1 # a zero value will raise ZeroDivisionError self.avg_metrics = avg_metrics super().__init__() self.update(iterable, **kwds) def _count_elements(self, iterable): """Tally elements from the iterable. This is copied from collections/__init__.py original code:: def _count_elements(mapping, iterable): 'Tally elements from the iterable.' mapping_get = mapping.get for elem in iterable: mapping[elem] = mapping_get(elem, 0) + 1 """ for elem in iterable: self[elem] = self.get(elem, 0) + 1 def __getitem__(self, key): if (self.avg_metrics is not None and key in self.avg_metrics): return self[key] / self._counter else: return self[key] def update(self, iterable=None, **kwds): if iterable is not None: if isinstance(iterable, Mapping): if self: self_get = self.get self._counter +=1 # local modification for elem, count in iterable.items(): self[elem] = count + self_get(elem, 0) else: super().update(iterable) else: self._count_elements(iterable) if kwds: self.update(kwds)
signature.asc
Description: OpenPGP digital signature
-- https://mail.python.org/mailman/listinfo/python-list