Tighten-up the docs for Counter().

This commit is contained in:
Raymond Hettinger 2009-01-21 23:12:51 +00:00
parent 4571f347f9
commit 0a1f7b8f72
2 changed files with 26 additions and 25 deletions

View File

@ -158,10 +158,9 @@ Notes on using :class:`Set` and :class:`MutableSet` as a mixin:
A counter tool is provided to support convenient and rapid tallies. A counter tool is provided to support convenient and rapid tallies.
For example:: For example::
# Tally repeated words in a list # Tally occurrences of words in a list
>>> words = ['red', 'blue', 'red', 'green', 'blue', 'blue']
>>> cnt = Counter() >>> cnt = Counter()
>>> for word in words: >>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
... cnt[word] += 1 ... cnt[word] += 1
>>> cnt >>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1}) Counter({'blue': 3, 'red': 2, 'green': 1})
@ -175,7 +174,7 @@ For example::
.. class:: Counter([iterable-or-mapping]) .. class:: Counter([iterable-or-mapping])
A :class:`Counter` is a :class:`dict` subclass for counting hashable items. A :class:`Counter` is a :class:`dict` subclass for counting hashable objects.
It is an unordered collection where elements are stored as dictionary keys It is an unordered collection where elements are stored as dictionary keys
and their counts are stored as dictionary values. Counts are allowed to be and their counts are stored as dictionary values. Counts are allowed to be
any integer value including zero or negative counts. The :class:`Counter` any integer value including zero or negative counts. The :class:`Counter`
@ -189,16 +188,15 @@ For example::
>>> c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping >>> c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping
>>> c = Counter(spam=8, eggs=1) # a new counter from keyword args >>> c = Counter(spam=8, eggs=1) # a new counter from keyword args
The returned object has a dictionary style interface except that it returns Counter objects have a dictionary interface except that they return a zero
a zero count for missing items (instead of raising a :exc:`KeyError` like a count for missing items instead of raising a :exc:`KeyError`::
dictionary would)::
>>> c = Counter(['egg', 'ham']) >>> c = Counter(['egg', 'ham'])
>>> c['bacon'] # count of a missing element is zero >>> c['bacon'] # count of a missing element is zero
0 0
Assigning a count of zero or reducing the count to zero leaves the Setting a count to zero still leaves an element in the dictionary. Use
element in the dictionary. Use ``del`` to remove the entry entirely: ``del`` to remove it entirely:
>>> c = Counter(['arthur', 'gwain']) >>> c = Counter(['arthur', 'gwain'])
>>> c['arthur'] = 0 # set the count of 'arthur' to zero >>> c['arthur'] = 0 # set the count of 'arthur' to zero
@ -214,9 +212,9 @@ For example::
.. method:: elements() .. method:: elements()
Return an iterator over elements repeating each as many times as its count. Return an iterator over elements repeating each as many times as its
Elements are returned in arbitrary order. If an element's count has been count. Elements are returned in arbitrary order. If an element's count
set to zero or a negative number, :meth:`elements` will ignore it. is less than one, :meth:`elements` will ignore it.
>>> c = Counter(a=4, b=2, c=0, d=-2) >>> c = Counter(a=4, b=2, c=0, d=-2)
>>> list(c.elements()) >>> list(c.elements())
@ -232,20 +230,18 @@ For example::
>>> Counter('abracadabra').most_common(3) >>> Counter('abracadabra').most_common(3)
[('a', 5), ('r', 2), ('b', 2)] [('a', 5), ('r', 2), ('b', 2)]
The usual dictionary methods are available for :class:`Counter` objects. The usual dictionary methods are available for :class:`Counter` objects
All of those work the same as they do for dictionaries except for two except for two which work differently for counters.
which work differently for counters.
.. method:: fromkeys(iterable) .. method:: fromkeys(iterable)
There is no equivalent class method for :class:`Counter` objects. This class method is not implemented for :class:`Counter` objects.
Raises a :exc:`NotImplementedError` when called.
.. method:: update([iterable-or-mapping]) .. method:: update([iterable-or-mapping])
Elements are counted from an *iterable* or added-in from another Elements are counted from an *iterable* or added-in from another
*mapping* (or counter). Like :meth:`dict.update` but adds-in counts *mapping* (or counter). Like :meth:`dict.update` but adds-in counts
instead of replacing them, and the *iterable* is expected to be a instead of replacing them. Also, the *iterable* is expected to be a
sequence of elements, not a sequence of ``(key, value)`` pairs:: sequence of elements, not a sequence of ``(key, value)`` pairs::
>>> c = Counter('which') >>> c = Counter('which')
@ -273,7 +269,7 @@ contain repeated elements (with counts of one or more). Addition and
subtraction combine counters by adding or subtracting the counts of subtraction combine counters by adding or subtracting the counts of
corresponding elements. Intersection and union return the minimum and maximum corresponding elements. Intersection and union return the minimum and maximum
of corresponding counts. All four multiset operations exclude results with of corresponding counts. All four multiset operations exclude results with
zero or negative counts:: counts less than one::
>>> c = Counter(a=3, b=1) >>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2) >>> d = Counter(a=1, b=2)
@ -291,9 +287,9 @@ zero or negative counts::
* `Bag class <http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html>`_ * `Bag class <http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html>`_
in Smalltalk. in Smalltalk.
* An early Python `Bag recipe <http://code.activestate.com/recipes/259174/>`_ * A `Counter <http://code.activestate.com/recipes/576611/>`_ conformant
for Python 2.4 and a `Counter <http://code.activestate.com/recipes/576611/>`_ recipe for Python 2.5 and an early Python `Bag recipe
comformant recipe for Python 2.5 and later. <http://code.activestate.com/recipes/259174/>`_ for Python 2.4.
* Wikipedia entry for `Multisets <http://en.wikipedia.org/wiki/Multiset>`_\. * Wikipedia entry for `Multisets <http://en.wikipedia.org/wiki/Multiset>`_\.
@ -304,9 +300,9 @@ zero or negative counts::
*Knuth, Donald. The Art of Computer Programming Volume II, *Knuth, Donald. The Art of Computer Programming Volume II,
Section 4.6.3, Exercise 19*\. Section 4.6.3, Exercise 19*\.
* To enumerate all possible distinct multisets of a given size over a given * To enumerate all distinct multisets of a given size over a given set of
set of inputs, see the :func:`combinations_with_replacement` function in elements, see the :func:`combinations_with_replacement` function in the
the :ref:`itertools-recipes` for itertools:: :ref:`itertools-recipes` for itertools::
map(Counter, combinations_with_replacement('abc', 2)) --> AA AB AC BB BC CC map(Counter, combinations_with_replacement('abc', 2)) --> AA AB AC BB BC CC

View File

@ -448,6 +448,11 @@ class TestCounter(unittest.TestCase):
self.assertEqual(dict(Counter(s)), dict(Counter(s).items())) self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
self.assertEqual(set(Counter(s)), set(s)) self.assertEqual(set(Counter(s)), set(s))
def test_invariant_for_the_in_operator(self):
c = Counter(a=10, b=-2, c=0)
for elem in c:
self.assert_(elem in c)
def test_multiset_operations(self): def test_multiset_operations(self):
# Verify that adding a zero counter will strip zeros and negatives # Verify that adding a zero counter will strip zeros and negatives
c = Counter(a=10, b=-2, c=0) + Counter() c = Counter(a=10, b=-2, c=0) + Counter()