The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Count hashable valuescounts = Counter(values)View examples
Get common valuestop = counts.most_common(3)View examples
Sum countssize = counts.total()View examples
Group valuesgroups = defaultdict(list)View examples
Initialize numeric countscounts = defaultdict(int)View examples
Add to the leftqueue.appendleft(item)View examples
Remove from the leftitem = queue.popleft()View examples
Keep a bounded historyhistory = deque(maxlen=100)View examples
Layer mappingsconfig = ChainMap(cli, environment, defaults)View examples
Add a child scopechild = config.new_child(overrides)View examples
Declare a tuple recordPoint = namedtuple('Point', ['x', 'y'])View examples
Copy with field changesmoved = point._replace(x=10)View examples
Push onto a min-heapheappush(heap, (priority, item))View examples
Pop the smallest entrypriority, item = heappop(heap)View examples
Select a few smallest valueslowest = nsmallest(3, values)View examples
Find a right insertion pointindex = bisect_right(values, target)View examples
Insert while sortedinsort(values, item)View examples

The right container makes intent visible and avoids accidental complexity. Start with built-in dict, list, set, and tuple; reach for collections when counting, grouping, layering mappings, or operating at both ends of a queue, and use heapq or bisect when you need incremental ordering without repeatedly sorting everything.

Step by step

Detailed examples

01

Count values and perform multiset arithmetic

Counter is a dict subclass whose missing keys read as zero. most_common preserves first-encounter order for equal counts, while arithmetic can combine inventories and drops zero or negative results from ordinary addition and subtraction outputs. Counter.total was added in Python 3.10; use sum(counter.values()) when supporting older versions.

Count and combine inventories
from collections import Counter

stock = Counter(['tea', 'coffee', 'tea', 'cocoa'])
delivery = Counter(tea=1, coffee=2)
print(stock['tea'], stock['water'])
print(stock.most_common(2))
print(sorted((stock + delivery).items()))
print(stock.total())
Output
2 0
[('tea', 2), ('coffee', 1)]
[('cocoa', 1), ('coffee', 3), ('tea', 3)]
4
Back to quick reference ↑
02

Create missing values only when indexed

defaultdict calls its zero-argument factory when __getitem__ encounters a missing key, stores the result, and returns it. Methods such as get do not invoke the factory. Prefer it for uniform grouping or accumulation; use setdefault when initialization depends on the current operation, and avoid factories with surprising side effects.

Group records in encounter order
from collections import defaultdict

records = [('fruit', 'pear'), ('tool', 'saw'), ('fruit', 'plum')]
groups = defaultdict(list)
for category, value in records:
    groups[category].append(value)

print(dict(groups))
print(groups.get('missing'))
print('missing' in groups)
Output
{'fruit': ['pear', 'plum'], 'tool': ['saw']}
None
False
Back to quick reference ↑
03

Use deque for queues and bounded histories

deque supports append and pop operations at either end in approximately O(1) time, while removing from the front of a list shifts remaining elements. A maxlen deque keeps only the newest bounded window. Individual indexing toward the middle is slower, so use a list when random access dominates.

Process a queue and retain recent results
from collections import deque

queue = deque(['build', 'test'])
queue.appendleft('lint')
history = deque(maxlen=2)
while queue:
    task = queue.popleft()
    history.append(task)
    print(f'run {task}')
print(list(history))
Output
run lint
run build
run test
['build', 'test']
Back to quick reference ↑
04

Layer configuration without merging dictionaries

ChainMap searches its mappings from first to last, making precedence explicit while retaining live links to the originals. Writes and deletions affect only the first mapping. new_child adds a scope at the front, and parents removes the current front scope; materialize with dict only when you need an independent snapshot.

Overlay command options on defaults
from collections import ChainMap

defaults = {'color': 'blue', 'retries': 2}
environment = {'retries': 4}
cli = {}
config = ChainMap(cli, environment, defaults)
print(config['color'], config['retries'])
config['color'] = 'green'
child = config.new_child({'retries': 1})
print(child['color'], child['retries'])
print(cli)
Output
blue 4
green 1
{'color': 'green'}
Back to quick reference ↑
05

Use named tuples for compact immutable records

namedtuple creates a tuple subclass, so values unpack, index, compare, and serialize like tuples while exposing readable field names. _replace returns a new value because records are immutable. For defaults, type annotations, validation, or evolving behavior, a frozen dataclass may communicate the model more clearly.

Read, unpack, and update a record
from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'], defaults=[0])
origin_side = Point(4)
print(origin_side.x, origin_side.y)
x, y = origin_side
print(x + y)
print(origin_side._replace(y=3))
Output
4 0
4
Point(x=4, y=3)
Back to quick reference ↑
06

Maintain a priority queue with heapq

heapq represents a min-heap inside a list: heap[0] is the smallest entry, but the remaining list is not globally sorted. Tuples compare field by field, so include a unique counter before a non-orderable payload when priorities can tie. nsmallest and nlargest suit small selections; sorted is usually clearer when selecting most of the input.

Resolve equal priorities with an insertion counter
from heapq import heappop, heappush, nsmallest

heap = []
for order, (priority, task) in enumerate([(2, 'docs'), (1, 'test'), (1, 'lint')]):
    heappush(heap, (priority, order, task))
while heap:
    priority, _, task = heappop(heap)
    print(priority, task)
print(nsmallest(2, [8, 3, 5, 1]))
Output
1 test
1 lint
2 docs
[1, 3]
Back to quick reference ↑
07

Search and update already sorted lists with bisect

bisect_left chooses the position before equal items and bisect_right chooses after them. insort performs the search efficiently, but inserting into a list remains O(n) because later elements move. It is effective for modest collections with occasional insertions; batch additions are often better followed by one sort.

Place scores around equal values
from bisect import bisect_left, bisect_right, insort

scores = [10, 20, 20, 40]
print(bisect_left(scores, 20), bisect_right(scores, 20))
insort(scores, 30)
print(scores)
print(scores[bisect_left(scores, 25):])
Output
1 3
[10, 20, 20, 30, 40]
[30, 40]
Back to quick reference ↑

Local code tester

Schedule tasks by priority

Add priorities, inspect the heap, and compare priority processing with a bounded recent-history deque.

Runs in your browser
Output
Press Run to load Python locally.

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. Python Software Foundationcollections — Container datatypesdocs.python.org
  2. Python Software Foundationheapq — Heap queue algorithmdocs.python.org
  3. Python Software Foundationbisect — Array bisection algorithmdocs.python.org
  4. Python Software FoundationTime Complexitywiki.python.org

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback