Skip to content

Commit dc1dba6

Browse files
committed
-
1 parent 18eae13 commit dc1dba6

File tree

4 files changed

+73
-17
lines changed

4 files changed

+73
-17
lines changed

source_py3/python_toolbox/collection_tools.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ def _get_all_contained_counters(counter, use_lazy_tuple=True):
3434
counter,
3535
(
3636
collections.Counter,
37-
nifty_collections.frozen_tally_and_frozen_ordered_tally.
38-
_FrozenTallyMixin
37+
nifty_collections.tallying._TallyMixin
3938
)
4039
)
4140
counter_type = type(counter)

source_py3/python_toolbox/nifty_collections/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
from .weak_key_identity_dict import WeakKeyIdentityDict
1010
from .lazy_tuple import LazyTuple
1111
from .frozen_dict_and_frozen_ordered_dict import FrozenDict, FrozenOrderedDict
12-
from .frozen_tally_and_frozen_ordered_tally import (FrozenTally,
13-
FrozenOrderedTally)
12+
from .tallying import Tally, OrderedTally, FrozenTally, FrozenOrderedTally
1413
from .frozen_tally_tally import FrozenTallyTally
1514
from .default_sorted_dict import DefaultSortedDict
1615
from .cute_enum import CuteEnum

source_py3/python_toolbox/nifty_collections/frozen_tally_tally.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from python_toolbox import math_tools
77

8-
from .frozen_tally_and_frozen_ordered_tally import FrozenTally
8+
from .tallying import FrozenTally
99

1010

1111
class FrozenTallyTally(FrozenTally):

source_py3/python_toolbox/nifty_collections/frozen_tally_and_frozen_ordered_tally.py renamed to source_py3/python_toolbox/nifty_collections/tallying.py

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def _count_elements(mapping, iterable):
2121
for element in iterable:
2222
mapping[element] = mapping_get(element, 0) + 1
2323

24-
class _FrozenTallyMixin:
24+
class _BaseTallyMixin:
2525
'''Mixin for `FrozenTally` and `FrozenOrderedTally`.'''
2626

2727
def __init__(self, iterable={}):
@@ -40,7 +40,7 @@ def __init__(self, iterable={}):
4040
if value < 0:
4141
raise TypeError(
4242
"You passed %s as the count of %s, while "
43-
"a `Tally` doesn't support negative amounts." %
43+
"`Tally` doesn't support negative amounts." %
4444
(value, key)
4545
)
4646

@@ -107,7 +107,7 @@ def __add__(self, other):
107107
FrozenTally({'b': 4, 'c': 2, 'a': 1})
108108
109109
'''
110-
if not isinstance(other, _FrozenTallyMixin):
110+
if not isinstance(other, _BaseTallyMixin):
111111
return NotImplemented
112112

113113
# Using `OrderedDict` to store interim results because
@@ -133,7 +133,7 @@ def __sub__(self, other):
133133
FrozenTally({'b': 2, 'a': 1})
134134
135135
'''
136-
if not isinstance(other, _FrozenTallyMixin):
136+
if not isinstance(other, _BaseTallyMixin):
137137
return NotImplemented
138138

139139
# Using `OrderedDict` to store interim results because
@@ -154,7 +154,7 @@ def __or__(self, other):
154154
FrozenTally({'b': 3, 'c': 2, 'a': 1})
155155
156156
'''
157-
if not isinstance(other, _FrozenTallyMixin):
157+
if not isinstance(other, _BaseTallyMixin):
158158
return NotImplemented
159159

160160
# Using `OrderedDict` to store interim results because
@@ -181,7 +181,7 @@ def __and__(self, other):
181181
FrozenTally({'b': 1})
182182
183183
'''
184-
if not isinstance(other, _FrozenTallyMixin):
184+
if not isinstance(other, _BaseTallyMixin):
185185
return NotImplemented
186186

187187
# Using `OrderedDict` to store interim results because
@@ -227,7 +227,7 @@ def frozen_tally_tally(self):
227227
# takes the items' order into account.
228228

229229
def __lt__(self, other):
230-
if not isinstance(other, _FrozenTallyMixin):
230+
if not isinstance(other, _BaseTallyMixin):
231231
return NotImplemented
232232
found_strict_difference = False # Until challenged.
233233
for element, count in self.items():
@@ -242,7 +242,7 @@ def __lt__(self, other):
242242
return found_strict_difference
243243

244244
def __le__(self, other):
245-
if not isinstance(other, _FrozenTallyMixin):
245+
if not isinstance(other, _BaseTallyMixin):
246246
return NotImplemented
247247
for element, count in self.items():
248248
try:
@@ -254,7 +254,7 @@ def __le__(self, other):
254254
return True
255255

256256
def __gt__(self, other):
257-
if not isinstance(other, _FrozenTallyMixin):
257+
if not isinstance(other, _BaseTallyMixin):
258258
return NotImplemented
259259
found_strict_difference = False # Until challenged.
260260
for element, count in self.items():
@@ -269,7 +269,7 @@ def __gt__(self, other):
269269
return found_strict_difference
270270

271271
def __ge__(self, other):
272-
if not isinstance(other, _FrozenTallyMixin):
272+
if not isinstance(other, _BaseTallyMixin):
273273
return NotImplemented
274274
for element, count in self.items():
275275
try:
@@ -280,8 +280,65 @@ def __ge__(self, other):
280280
return False
281281
return True
282282

283+
284+
class _TallyMixin(_BaseTallyMixin):
285+
# blocktodo: add all mutable methods, like __iadd__ and everything
286+
pass
287+
288+
289+
class _OrderedTallyMixin:
290+
def __repr__(self):
291+
if not self:
292+
return '%s()' % type(self).__name__
293+
return '%s(%s)' % (
294+
type(self).__name__,
295+
'[%s]' % ', '.join('%s' % (item,) for item in self.items())
296+
)
297+
298+
299+
class Tally(_TallyMixin, FrozenDict):
300+
'''
301+
blocktododoc
302+
An immutable tally.
303+
304+
A tally that (a) can't be changed and (b) has only positive integer values.
305+
This is like `collections.Counter`, except:
306+
307+
- Because it's immutable, it's also hashable, and thus it can be used as a
308+
key in dicts and sets.
309+
310+
- Unlike `collections.Counter`, we don't think of it as a "dict who
311+
happens to count objects" but as an object that is absolutely intended
312+
for counting objects. This means we do not allow arbitrary values for
313+
counts like `collections.Counter` and we don't have to deal with a
314+
class that has an identity crisis and doesn't know whether it's a
315+
counter or a dict.
316+
317+
'''
318+
319+
class OrderedTally(_TallyMixin, FrozenDict):
320+
'''
321+
blocktododoc
322+
An immutable, ordered tally.
323+
324+
A tally that (a) can't be changed and (b) has only positive integer values.
325+
This is like `collections.Counter`, except:
326+
327+
- Because it's immutable, it's also hashable, and thus it can be used as a
328+
key in dicts and sets.
329+
330+
- Unlike `collections.Counter`, we don't think of it as a "dict who
331+
happens to count objects" but as an object that is absolutely intended
332+
for counting objects. This means we do not allow arbitrary values for
333+
counts like `collections.Counter` and we don't have to deal with a
334+
class that has an identity crisis and doesn't know whether it's a
335+
counter or a dict.
336+
337+
- It has an order to its elements, like `collections.OrderedDict`.
338+
339+
'''
283340

284-
class FrozenTally(_FrozenTallyMixin, FrozenDict):
341+
class FrozenTally(_BaseTallyMixin, FrozenDict):
285342
'''
286343
An immutable tally.
287344
@@ -300,7 +357,8 @@ class that has an identity crisis and doesn't know whether it's a
300357
301358
'''
302359

303-
class FrozenOrderedTally(_FrozenTallyMixin, FrozenOrderedDict):
360+
class FrozenOrderedTally(_OrderedTallyMixin, _BaseTallyMixin,
361+
FrozenOrderedDict):
304362
'''
305363
An immutable, ordered tally.
306364

0 commit comments

Comments
 (0)