8.3. collections — High-performance container datatypes¶
New in version 2.4.
Source code: Lib/collections.py and Lib/_abcoll.py
This module implements specialized container datatypes providing alternatives to
Python’s general purpose built-in containers, dict, list,
set, and tuple.
factory function for creating tuple subclasses with named fields |
New in version 2.6. |
|
list-like container with fast appends and pops on either end |
New in version 2.4. |
|
dict subclass for counting hashable objects |
New in version 2.7. |
|
dict subclass that remembers the order entries were added |
New in version 2.7. |
|
dict subclass that calls a factory function to supply missing values |
New in version 2.5. |
In addition to the concrete container classes, the collections module provides abstract base classes that can be used to test whether a class provides a particular interface, for example, whether it is hashable or a mapping.
8.3.1. Counter objects¶
A counter tool is provided to support convenient and rapid tallies. For example:
>>> # Tally occurrences of words in a list
>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
... cnt[word] += 1
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})
>>> # Find the ten most common words in Hamlet
>>> import re
>>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]
-
class
collections.Counter([iterable-or-mapping])¶ A
Counteris adictsubclass for counting hashable objects. 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 any integer value including zero or negative counts. TheCounterclass is similar to bags or multisets in other languages.Elements are counted from an iterable or initialized from another mapping (or counter):
>>> c = Counter() # a new, empty counter >>> c = Counter('gallahad') # a new counter from an iterable >>> c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping >>> c = Counter(cats=4, dogs=8) # a new counter from keyword args
Counter objects have a dictionary interface except that they return a zero count for missing items instead of raising a
KeyError:>>> c = Counter(['eggs', 'ham']) >>> c['bacon'] # count of a missing element is zero 0
Setting a count to zero does not remove an element from a counter. Use
delto remove it entirely:>>> c['sausage'] = 0 # counter entry with a zero count >>> del c['sausage'] # del actually removes the entry
New in version 2.7.
Counter objects support three methods beyond those available for all dictionaries:
-
elements()¶ Return an iterator over elements repeating each as many times as its count. Elements are returned in arbitrary order. If an element’s count is less than one,
elements()will ignore it.>>> c = Counter(a=4, b=2, c=0, d=-2) >>> list(c.elements()) ['a', 'a', 'a', 'a', 'b', 'b']
-
most_common([n])¶ Return a list of the n most common elements and their counts from the most common to the least. If n is omitted or
None,most_common()returns all elements in the counter. Elements with equal counts are ordered arbitrarily:>>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)]
-
subtract([iterable-or-mapping])¶ Elements are subtracted from an iterable or from another mapping (or counter). Like
dict.update()but subtracts counts instead of replacing them. Both inputs and outputs may be zero or negative.>>> c = Counter(a=4, b=2, c=0, d=-2) >>> d = Counter(a=1, b=2, c=3, d=4) >>> c.subtract(d) >>> c Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
The usual dictionary methods are available for
Counterobjects except for two which work differently for counters.-
update([iterable-or-mapping])¶ Elements are counted from an iterable or added-in from another mapping (or counter). Like
dict.update()but adds counts instead of replacing them. Also, the iterable is expected to be a sequence of elements, not a sequence of(key, value)pairs.
-
Common patterns for working with Counter objects:
sum(c.values()) # total of all counts
c.clear() # reset all counts
list(c) # list unique elements
set(c) # convert to a set
dict(c) # convert to a regular dictionary
c.items() # convert to a list of (elem, cnt) pairs
Counter(dict(list_of_pairs)) # convert from a list of (elem, cnt) pairs
c.most_common()[:-n-1:-1] # n least common elements
c += Counter() # remove zero and negative counts
Several mathematical operations are provided for combining Counter
objects to produce multisets (counters that have counts greater than zero).
Addition and subtraction combine counters by adding or subtracting the counts
of corresponding elements. Intersection and union return the minimum and
maximum of corresponding counts. Each operation can accept inputs with signed
counts, but the output will exclude results with counts of zero or less.
>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d # add two counters together: c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d # subtract (keeping only positive counts)
Counter({'a': 2})
>>> c & d # intersection: min(c[x], d[x])
Counter({'a': 1, 'b': 1})
>>> c | d # union: max(c[x], d[x])
Counter({'a': 3, 'b': 2})
Note
Counters were primarily designed to work with positive integers to represent running counts; however, care was taken to not unnecessarily preclude use cases needing other types or negative values. To help with those use cases, this section documents the minimum range and type restrictions.
The
Counterclass itself is a dictionary subclass with no restrictions on its keys and values. The values are intended to be numbers representing counts, but you could store anything in the value field.The
most_common()method requires only that the values be orderable.For in-place operations such as
c[key] += 1, the value type need only support addition and subtraction. So fractions, floats, and decimals would work and negative values are supported. The same is also true forupdate()andsubtract()which allow negative and zero values for both inputs and outputs.The multiset methods are designed only for use cases with positive values. The inputs may be negative or zero, but only outputs with positive values are created. There are no type restrictions, but the value type needs to support addition, subtraction, and comparison.
The
elements()method requires integer counts. It ignores zero and negative counts.
See also
Counter class adapted for Python 2.5 and an early Bag recipe for Python 2.4.
Bag class in Smalltalk.
Wikipedia entry for Multisets.
C++ multisets tutorial with examples.
For mathematical operations on multisets and their use cases, see Knuth, Donald. The Art of Computer Programming Volume II, Section 4.6.3, Exercise 19.
To enumerate all distinct multisets of a given size over a given set of elements, see
itertools.combinations_with_replacement().map(Counter, combinations_with_replacement(‘ABC’, 2)) –> AA AB AC BB BC CC
8.3.2. deque objects¶
-
class
collections.deque([iterable[, maxlen]])¶ Returns a new deque object initialized left-to-right (using
append()) with data from iterable. If iterable is not specified, the new deque is empty.Deques are a generalization of stacks and queues (the name is pronounced “deck” and is short for “double-ended queue”). Deques support thread-safe, memory efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction.
Though
listobjects support similar operations, they are optimized for fast fixed-length operations and incur O(n) memory movement costs forpop(0)andinsert(0, v)operations which change both the size and position of the underlying data representation.New in version 2.4.
If maxlen is not specified or is
None, deques may grow to an arbitrary length. Otherwise, the deque is bounded to the specified maximum length. Once a bounded length deque is full, when new items are added, a corresponding number of items are discarded from the opposite end. Bounded length deques provide functionality similar to thetailfilter in Unix. They are also useful for tracking transactions and other pools of data where only the most recent activity is of interest.Changed in version 2.6: Added maxlen parameter.
Deque objects support the following methods:
-
append(x)¶ Add x to the right side of the deque.
-
appendleft(x)¶ Add x to the left side of the deque.
-
clear()¶ Remove all elements from the deque leaving it with length 0.
-
count(x)¶ Count the number of deque elements equal to x.
New in version 2.7.
-
extend(iterable)¶ Extend the right side of the deque by appending elements from the iterable argument.
-
extendleft(iterable)¶ Extend the left side of the deque by appending elements from iterable. Note, the series of left appends results in reversing the order of elements in the iterable argument.
-
pop()¶ Remove and return an element from the right side of the deque. If no elements are present, raises an
IndexError.
-
popleft()¶ Remove and return an element from the left side of the deque. If no elements are present, raises an
IndexError.
-
remove(value)¶ Remove the first occurrence of value. If not found, raises a
ValueError.New in version 2.5.
-
reverse()¶ Reverse the elements of the deque in-place and then return
None.New in version 2.7.
-
rotate(n=1)¶ Rotate the deque n steps to the right. If n is negative, rotate to the left.
When the deque is not empty, rotating one step to the right is equivalent to
d.appendleft(d.pop()), and rotating one step to the left is equivalent tod.append(d.popleft()).
Deque objects also provide one read-only attribute:
-
maxlen¶ Maximum size of a deque or
Noneif unbounded.New in version 2.7.
-
In addition to the above, deques support iteration, pickling, len(d),
reversed(d), copy.copy(d), copy.deepcopy(d), membership testing with
the in operator, and subscript references such as d[-1]. Indexed
access is O(1) at both ends but slows to O(n) in the middle. For fast random
access, use lists instead.
Example:
>>> from collections import deque
>>> d = deque('ghi') # make a new deque with three items
>>> for elem in d: # iterate over the deque's elements
... print elem.upper()
G
H
I
>>> d.append('j') # add a new entry to the right side
>>> d.appendleft('f') # add a new entry to the left side
>>> d # show the representation of the deque
deque(['f', 'g', 'h', 'i', 'j'])
>>> d.pop() # return and remove the rightmost item
'j'
>>> d.popleft() # return and remove the leftmost item
'f'
>>> list(d) # list the contents of the deque
['g', 'h', 'i']
>>> d[0] # peek at leftmost item
'g'
>>> d[-1] # peek at rightmost item
'i'
>>> list(reversed(d)) # list the contents of a deque in reverse
['i', 'h', 'g']
>>> 'h' in d # search the deque
True
>>> d.extend('jkl') # add multiple elements at once
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> d.