PythiloLesson 22 of 30 · progress kept in this browser

The collections module

You have met Counter. The rest of collections holds more containers for jobs that plain lists and dicts do awkwardly.

from collections import (
    Counter, defaultdict, deque, namedtuple)

stock = Counter(apple=3, pear=1)
sold = Counter(apple=1, pear=2)
print(stock - sold, stock + sold)

spent = defaultdict(int)
orders = [("ann", 5), ("bo", 2), ("ann", 1)]
for name, amount in orders:
    spent[name] += amount
print(dict(spent))

recent = deque("abcde", maxlen=3)
recent.appendleft("z")
print(recent)

Point = namedtuple("Point", "x y")
p = Point(1, 2)
print(p.x, p._replace(y=5), p._asdict())
  • Counters add and subtract, and the result drops any count that falls to zero or below, which suits stock and shopping lists.
  • defaultdict calls its factory for a missing key: int gives 0 for totals, list an empty group, set an empty set.
  • deque adds and removes at both ends in constant time, where list.pop(0) shifts every item. With maxlen, items fall off the far end.
  • namedtuple is a tuple with field names. _replace returns a changed copy and _asdict a dict.
Your task

Write shortfall(needed, have) returning a dict of how many of each item in the list needed are still missing after using the list have, with no zero entries. Write totals(pairs) summing the amounts of (name, amount) pairs per name into a plain dict. Write tail(items, n) returning the last n items of any iterable as a list. Define Card = namedtuple("Card", "rank suit").