AI Skill Report Card

Using Collections Module

A-85·Aug 22, 2026·Source: Web
15 / 15
Python
from collections import namedtuple, deque, ChainMap, Counter, defaultdict, OrderedDict # Named fields instead of index access Point = namedtuple('Point', ['x', 'y']) p = Point(1, 2) # p.x == 1 # Fast appends/pops from both ends (O(1) vs list's O(n)) dq = deque([1, 2, 3]) dq.appendleft(0) dq.pop() # Frequency counting c = Counter("abracadabra") c.most_common(2) # [('a', 5), ('b', 2)] # Auto-initializing dict d = defaultdict(list) d['key'].append(1) # no KeyError, no manual init
Recommendation
Add a 'bad vs good' code comparison example to more strongly demonstrate anti-patterns from Common Pitfalls
14 / 15
  1. Identify the access pattern driving container choice:

    • Counting/tallying → Counter
    • Queue/stack/sliding window → deque
    • Tuple with named fields, immutable record → namedtuple
    • Layered/fallback lookups across multiple dicts → ChainMap
    • Need dict but with default values on missing key → defaultdict
    • Need insertion-order guarantees pre-3.7 or move_to_endOrderedDict (note: plain dict is ordered since 3.7; use OrderedDict mainly for equality-by-order semantics or move_to_end)
    • Need to subclass dict/list/str behavior → UserDict/UserList/UserString
  2. Pick the right constructor/factory:

    • namedtuple(typename, field_names) — supports _asdict(), _replace(), _fields, defaults via defaults= param
    • deque(iterable, maxlen=N)maxlen gives a fixed-size rolling buffer
    • Counter(iterable_or_mapping) — supports +, -, &, | set-like operations
    • defaultdict(default_factory) — factory called with no args (e.g. list, int, set, or a lambda)
    • ChainMap(*maps) — writes go to first map only; use new_child() for scoped updates
  3. Use built-in methods over manual logic:

    • Counter.most_common(n) instead of sorting manually
    • deque.rotate(n) instead of slicing tricks
    • namedtuple._replace(**kwargs) instead of rebuilding tuples
    • ChainMap.maps to inspect/reorder the underlying list of mappings
  4. Verify performance assumptions — deque is O(1) at both ends but O(n) for random access (dq[i] is slow); use list if you need indexing-heavy access.

Recommendation
Include a brief example of UserDict/UserList subclassing since it's mentioned but never shown in code
17 / 20

Example 1: Input: Track word frequency in a large text and get the top 5 words. Output:

Python
from collections import Counter words = text.lower().split() Counter(words).most_common(5)

Example 2: Input: Implement a sliding window of the last N items seen in a stream. Output:

Python
from collections import deque window = deque(maxlen=N) for item in stream: window.append(item) # oldest auto-evicted

Example 3: Input: Build a config system where user settings override defaults override built-ins. Output:

Python
from collections import ChainMap config = ChainMap(user_settings, defaults, builtins) config['theme'] # checks user_settings first, falls through

Example 4: Input: Group a list of (key, value) pairs into a dict of lists without checking for key existence. Output:

Python
from collections import defaultdict grouped = defaultdict(list) for k, v in pairs: grouped[k].append(v)
Recommendation
Consider a decision table mapping problem symptoms to specific collections type for faster scanning
  • Prefer Counter arithmetic (c1 - c2, c1 & c2) over manual dict merging loops.
  • Use namedtuple(..., defaults=(...)) to avoid repetitive constructor calls when some fields are usually constant.
  • For defaultdict, pick the factory to match desired zero-value: int → 0, list → [], set → set().
  • Convert OrderedDict comparisons only when order matters for equality — plain dicts compare by content regardless of order.
  • Use ChainMap.new_child(m) to push a temporary scope (e.g., for nested function contexts) rather than copying/merging dicts.
  • When subclassing built-in types with extra invariants, prefer UserDict/UserList/UserString over subclassing dict/list/str directly — they avoid subtle bugs where built-in methods bypass overridden methods.
  • Don't index into a deque in a hot loop — it's O(n); convert to list first if random access is needed repeatedly.
  • Don't forget Counter[missing_key] returns 0 instead of raising KeyError — this can mask bugs when you actually wanted to detect missing keys.
  • Don't mutate a defaultdict's structure through membership checks (if key in d) after accidentally accessing d[key] — the access itself inserts the default value.
  • Don't assume ChainMap writes propagate to all layers — chainmap[key] = value only ever modifies chainmap.maps[0].
  • Don't use mutable default factories carelessly, e.g. defaultdict(lambda: []) is fine, but sharing a single mutable object across keys (defaultdict(lambda: shared_list)) causes cross-key mutation bugs.
  • Don't rely on OrderedDict-specific behavior when a plain dict suffices — added complexity without benefit in Python 3.7+.
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
15/15
Workflow
14/15
Examples
17/20
Completeness
18/20
Format
14/15
Conciseness
14/15