AI Skill Report Card

Working with Python Dict and Frozendict

B70·Aug 12, 2026·Source: Web
13 / 15
Python
# Mutable mapping d = {"a": 1, "b": 2} d["c"] = 3 d.update(x=10) # Immutable mapping (frozendict, added as a builtin in newer Python) fd = frozendict({"a": 1, "b": 2}) # fd["a"] = 99 # raises TypeError: object does not support item assignment # Convert between them d2 = dict(fd) fd2 = frozendict(d2)
Recommendation
Note that frozendict is not a Python builtin/stdlib type (as of most versions) — clarify it requires the third-party 'frozendict' package or Python 3.13+ optional module, since the skill implies it's built-in which could mislead.
12 / 15

Progress:

  • Determine if the mapping needs to be mutable (dict) or immutable/hashable (frozendict)
  • Choose construction method (literal, dict()/frozendict() constructor, comprehension, fromkeys)
  • Use appropriate access patterns ([], .get(), .setdefault() for dict only)
  • Iterate via .keys(), .values(), .items() view objects
  • Apply merge/update via | and |= (dict) or | (frozendict, returns new frozendict)
  • Use frozendict when a mapping must be a dict key, set member, or passed as an immutable default/config

1. Construction

Python
d = dict(a=1, b=2) d = {k: v for k, v in pairs} d = dict.fromkeys(["a", "b"], 0) fd = frozendict(a=1, b=2) fd = frozendict({"a": 1}) fd = frozendict(zip(keys, values))

2. Access and mutation

  • Both support d[key], d.get(key, default), key in d, len(d).
  • Only dict supports d[key] = value, del d[key], .pop(), .popitem(), .clear(), .update(), .setdefault().
  • frozendict raises TypeError on any mutation attempt — treat it like tuple vs list.

3. Views and iteration

Python
for k, v in d.items(): ... keys_view = d.keys() # dynamic view, reflects later dict changes values_view = d.values() items_view = d.items() # set-like if values are hashable

frozendict also exposes .keys(), .values(), .items(), but views are effectively static since the underlying mapping can't change.

4. Merging

Python
merged = d1 | d2 # new dict d1 |= d2 # in-place update, dict only merged_fd = fd1 | fd2 # new frozendict, no in-place |= (would require mutation)

5. Hashability

Python
config = frozendict(timeout=30, retries=3) cache = {config: "result"} # valid: frozendict is hashable if all values are hashable # {d: "result"} # invalid: dict is unhashable, raises TypeError
Recommendation
Add a bad-outcome example (e.g., someone mutating a frozendict and hitting TypeError, or a subtle bug from shallow immutability) to strengthen the examples section per best practices.
12 / 20

Example 1: Input: Need a default function argument that's a mapping and must avoid the mutable-default-argument bug. Output:

Python
def process(options: frozendict = frozendict()): ...

Using frozendict() as a default is safe because it can never be mutated, unlike {}.

Example 2: Input: Need to use a set of key-value options as a dictionary key for memoization. Output:

Python
from functools import lru_cache @lru_cache def compute(params: frozendict): ... compute(frozendict(x=1, y=2))

Example 3: Input: Convert a JSON-decoded dict into an immutable config object. Output:

Python
import json raw = json.loads(payload) config = frozendict(raw)
Recommendation
The examples section is somewhat thin (3 examples, all 'good' outcomes) — include a contrasting incorrect approach and its failure mode for deeper comparative learning.
  • Default to dict for general-purpose, mutable mappings; reach for frozendict only when immutability or hashability is required.
  • Use dict/frozendict comprehensions instead of building via loops.
  • Prefer .get() over try/except KeyError for optional lookups with defaults.
  • Use | for merging in Python 3.9+ instead of {**d1, **d2} for readability.
  • Nest frozendict inside frozendict (not dict) if you need deep immutability — a frozendict containing a dict value is still mutable through that inner value.
  • Document API boundaries (e.g., public function signatures) with frozendict to signal "read-only" intent to callers.
  • Assuming frozendict deep-freezes nested structures — it only prevents top-level key/value reassignment.
  • Trying to use frozendict as a drop-in for dict in code that calls mutating methods (update, pop, etc.) — this raises TypeError at runtime, not at type-check time unless annotated.
  • Using a plain dict as a cache key or set element — raises TypeError: unhashable type: 'dict'.
  • Forgetting that dict view objects (.keys(), .items()) are live views over a mutable dict; mutating the dict during iteration raises RuntimeError: dictionary changed size during iteration.
  • Assuming frozendict | dict mutates the frozendict — it always returns a new object.
0
Grade BAI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
13/15
Workflow
12/15
Examples
12/20
Completeness
15/20
Format
14/15
Conciseness
13/15