Welcome to part one of our Python 3 features series! Today, we’re diving into the handy tools in the collections module that can make your code cleaner and faster.

Python’s built-in containers (list, dict, set, tuple) are great, but sometimes you need a bit more power. Enter the collections module:

1. deque: Double-Ended Queue

A deque lets you push and pop from both ends in constant time. Perfect for queues, sliding windows, or undo/redo stacks.

from collections import deque

dq = deque([1, 2, 3])
dq.append(4)       # add at right
q.appendleft(0)   # add at left
print(dq)  # deque([0, 1, 2, 3, 4])

dq.pop()      # remove right end -> 4
dq.popleft()  # remove left end -> 0

2. Counter: Quick Counts

Want to tally up items? Counter counts each element for you.

from collections import Counter

words = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
c = Counter(words)
print(c)                # Counter({'apple': 3, 'banana': 2, 'orange': 1})
print(c.most_common(2)) # [('apple', 3), ('banana', 2)]

You can even add or subtract Counters, which is great for comparing two sets of data.

3. defaultdict: No More KeyErrors

With a defaultdict, you give a factory for missing keys, no more KeyError surprises.

from collections import defaultdict

d = defaultdict(int)
for ch in 'banana':
    d[ch] += 1
print(d)  # {'b': 1, 'a': 3, 'n': 2}

# Use any factory you like
dd = defaultdict(list)
dd['letters'].append('a')
print(dd)  # {'letters': ['a']}

4. OrderedDict: Control Your Order

Before Python 3.7, regular dicts didn’t keep order. Even now, OrderedDict gives you extra tricks like moving items around.

from collections import OrderedDict

od = OrderedDict(a=1, b=2, c=3)
od.move_to_end('a')
print(od)  # OrderedDict([('b', 2), ('c', 3), ('a', 1)])

Handy for LRU caches or any time you need to shuffle the order.

5. namedtuple: Readable, Lightweight Records

Need a simple class to bundle data? namedtuple gives you fields with almost zero overhead.

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y)  # 10 20
print(p)         # Point(x=10, y=20)

You get tuple behaviors plus named access, and it’s immutable!


That’s it for a quick tour of collections. Next time, we’ll see how yield from and enhanced generators can level up your code. Happy coding!