When a learner can reproduce a familiar example but a small variation causes confusion, the problem is usually an incomplete model rather than a lack of effort. The fastest useful response is to expose the hidden state and test one boundary at a time.
Python functools.lru_cache wraps a callable with a memoizing cache: a completed call can be reused when a later call has the same cache key. Mastery means deciding whether the function is safe to cache, predicting which calls share a key, measuring hits and misses, controlling lifetime and recognising when invalidation or asynchronous work requires another design. This guide begins with that mechanism, then develops it through worked traces, deliberate mistakes, explained practice and transfer decisions.
The aim is independent reasoning. A learner should be able to predict behaviour, locate the earliest wrong assumption, use a safe diagnostic procedure and defend a design choice in a new project.
Punggol families can use the guide in short sessions around homework, CCAs and rest. The activities are proposed learning exercises, not claims about a physical branch, timetable, class size, fee, school relationship or guaranteed result.
Use disposable data and repositories, preserve backups, and check version-sensitive details against the official source. Current documentation settles a technical contract; observation and explanation turn that contract into usable knowledge.
Find your next learning step
Choose the route that matches the present difficulty. Use the complete index for a systematic course.
Build the model
Chapters 1-4 . Begin here, then continue after the learner can predict, verify and explain.
Use the core tools
Chapters 5-8 . Begin here, then continue after the learner can predict, verify and explain.
Handle boundaries
Chapters 9-12 . Begin here, then continue after the learner can predict, verify and explain.
Debug and verify
Chapters 13-16 . Begin here, then continue after the learner can predict, verify and explain.
Transfer with judgment
Chapters 17-20 . Begin here, then continue after the learner can predict, verify and explain.
Open the full chapter index . Jump to capstone practice . Use the How Studying Works hub . Read the official documentation
Complete chapter index
Chapters 1-4 . Build the model
Chapters 5-8 . Use the core tools
Chapters 9-12 . Handle boundaries
Chapters 13-16 . Debug and verify
Chapters 17-20 . Transfer with judgment
lru_cache returns a wrapper that maps argument-derived keys to completed return values and tracks recent use for eviction. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is describing caching as making the original function intrinsically faster. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Count actual function-body executions and wrapper calls separately, then inspect cache_info.
For the The wrapper-and-key mental model chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on describing caching as making the original function intrinsically faster. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
from functools import lru_cache
@lru_cache(maxsize=4)
def square(n):
print('run', n)
return n*nExplained result. Calling square(3) twice prints once: the second call finds the same key and reuses 9. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: revision planner. Predict the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “lru_cache returns a wrapper that maps argument-derived keys to completed return values and tracks recent use for eviction.” Apply this procedure: Count actual function-body executions and wrapper calls separately, then inspect cache_info. The expected mechanism is: Calling square(3) twice prints once: the second call finds the same key and reuses 9. For the revision planner, add one near-miss that exposes describing caching as making the original function intrinsically faster. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: route exercise. Contrast the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “lru_cache returns a wrapper that maps argument-derived keys to completed return values and tracks recent use for eviction.” Apply this procedure: Count actual function-body executions and wrapper calls separately, then inspect cache_info. The expected mechanism is: Calling square(3) twice prints once: the second call finds the same key and reuses 9. For the route exercise, add one near-miss that exposes describing caching as making the original function intrinsically faster. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: library lookup. Stress-test the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “lru_cache returns a wrapper that maps argument-derived keys to completed return values and tracks recent use for eviction.” Apply this procedure: Count actual function-body executions and wrapper calls separately, then inspect cache_info. The expected mechanism is: Calling square(3) twice prints once: the second call finds the same key and reuses 9. For the library lookup, add one near-miss that exposes describing caching as making the original function intrinsically faster. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: science table. Explain the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “lru_cache returns a wrapper that maps argument-derived keys to completed return values and tracks recent use for eviction.” Apply this procedure: Count actual function-body executions and wrapper calls separately, then inspect cache_info. The expected mechanism is: Calling square(3) twice prints once: the second call finds the same key and reuses 9. For the science table, add one near-miss that exposes describing caching as making the original function intrinsically faster. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers describing caching as making the original function intrinsically faster.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Count actual function-body executions and wrapper calls separately, then inspect cache_info.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from The wrapper-and-key mental model?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing describing caching as making the original function intrinsically faster be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny budget model with a repeated tax calculation from immutable rates. Include one ordinary case, one boundary and one deliberate failure caused by describing caching as making the original function intrinsically faster. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: lru_cache returns a wrapper that maps argument-derived keys to completed return values and tracks recent use for eviction. It shows a trace, not only a final value. The ordinary case should demonstrate “Calling square(3) twice prints once: the second call finds the same key and reuses 9.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Count actual function-body executions and wrapper calls separately, then inspect cache_info. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For The wrapper-and-key mental model, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Every positional and keyword argument used in a cached call must be hashable because it participates in a dictionary-like key. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is passing a list because the function itself never mutates it. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Convert stable sequence inputs to tuples or redesign the boundary, and test the call before measuring speed.
For the Arguments must be hashable chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on passing a list because the function itself never mutates it. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache
def total(values): return sum(values)
total((2,4,6))Explained result. The tuple is hashable and can form a key; total([2,4,6]) raises TypeError before the body runs. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: library lookup. Contrast the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Every positional and keyword argument used in a cached call must be hashable because it participates in a dictionary-like key.” Apply this procedure: Convert stable sequence inputs to tuples or redesign the boundary, and test the call before measuring speed. The expected mechanism is: The tuple is hashable and can form a key; total([2,4,6]) raises TypeError before the body runs. For the library lookup, add one near-miss that exposes passing a list because the function itself never mutates it. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: science table. Stress-test the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Every positional and keyword argument used in a cached call must be hashable because it participates in a dictionary-like key.” Apply this procedure: Convert stable sequence inputs to tuples or redesign the boundary, and test the call before measuring speed. The expected mechanism is: The tuple is hashable and can form a key; total([2,4,6]) raises TypeError before the body runs. For the science table, add one near-miss that exposes passing a list because the function itself never mutates it. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: quiz generator. Explain the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Every positional and keyword argument used in a cached call must be hashable because it participates in a dictionary-like key.” Apply this procedure: Convert stable sequence inputs to tuples or redesign the boundary, and test the call before measuring speed. The expected mechanism is: The tuple is hashable and can form a key; total([2,4,6]) raises TypeError before the body runs. For the quiz generator, add one near-miss that exposes passing a list because the function itself never mutates it. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: budget model. Transfer the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Every positional and keyword argument used in a cached call must be hashable because it participates in a dictionary-like key.” Apply this procedure: Convert stable sequence inputs to tuples or redesign the boundary, and test the call before measuring speed. The expected mechanism is: The tuple is hashable and can form a key; total([2,4,6]) raises TypeError before the body runs. For the budget model, add one near-miss that exposes passing a list because the function itself never mutates it. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers passing a list because the function itself never mutates it.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Convert stable sequence inputs to tuples or redesign the boundary, and test the call before measuring speed.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Arguments must be hashable?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing passing a list because the function itself never mutates it be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny text analysis with a word feature function called across many sentences. Include one ordinary case, one boundary and one deliberate failure caused by passing a list because the function itself never mutates it. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Every positional and keyword argument used in a cached call must be hashable because it participates in a dictionary-like key. It shows a trace, not only a final value. The ordinary case should demonstrate “The tuple is hashable and can form a key; total([2,4,6]) raises TypeError before the body runs.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Convert stable sequence inputs to tuples or redesign the boundary, and test the call before measuring speed. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Arguments must be hashable, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Distinct argument patterns can occupy distinct cache entries even when the wrapped function would receive equivalent values. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is assuming every semantically equivalent call is automatically canonicalised. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Choose one calling convention or normalise before the cached boundary, then compare misses.
For the Cache keys follow call form chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on assuming every semantically equivalent call is automatically canonicalised. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache
def combine(a,b): return a+b
combine(a=1,b=2); combine(b=2,a=1)Explained result. The documentation warns that different keyword order can produce separate cache entries, so code should not depend on automatic canonicalisation. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: quiz generator. Stress-test the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Distinct argument patterns can occupy distinct cache entries even when the wrapped function would receive equivalent values.” Apply this procedure: Choose one calling convention or normalise before the cached boundary, then compare misses. The expected mechanism is: The documentation warns that different keyword order can produce separate cache entries, so code should not depend on automatic canonicalisation. For the quiz generator, add one near-miss that exposes assuming every semantically equivalent call is automatically canonicalised. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: budget model. Explain the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Distinct argument patterns can occupy distinct cache entries even when the wrapped function would receive equivalent values.” Apply this procedure: Choose one calling convention or normalise before the cached boundary, then compare misses. The expected mechanism is: The documentation warns that different keyword order can produce separate cache entries, so code should not depend on automatic canonicalisation. For the budget model, add one near-miss that exposes assuming every semantically equivalent call is automatically canonicalised. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: text analysis. Transfer the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Distinct argument patterns can occupy distinct cache entries even when the wrapped function would receive equivalent values.” Apply this procedure: Choose one calling convention or normalise before the cached boundary, then compare misses. The expected mechanism is: The documentation warns that different keyword order can produce separate cache entries, so code should not depend on automatic canonicalisation. For the text analysis, add one near-miss that exposes assuming every semantically equivalent call is automatically canonicalised. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: debug lab. Predict the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Distinct argument patterns can occupy distinct cache entries even when the wrapped function would receive equivalent values.” Apply this procedure: Choose one calling convention or normalise before the cached boundary, then compare misses. The expected mechanism is: The documentation warns that different keyword order can produce separate cache entries, so code should not depend on automatic canonicalisation. For the debug lab, add one near-miss that exposes assuming every semantically equivalent call is automatically canonicalised. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers assuming every semantically equivalent call is automatically canonicalised.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Choose one calling convention or normalise before the cached boundary, then compare misses.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Cache keys follow call form?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing assuming every semantically equivalent call is automatically canonicalised be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny debug lab with a counter proving which calls execute and which return cached values. Include one ordinary case, one boundary and one deliberate failure caused by assuming every semantically equivalent call is automatically canonicalised. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Distinct argument patterns can occupy distinct cache entries even when the wrapped function would receive equivalent values. It shows a trace, not only a final value. The ordinary case should demonstrate “The documentation warns that different keyword order can produce separate cache entries, so code should not depend on automatic canonicalisation.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Choose one calling convention or normalise before the cached boundary, then compare misses. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Cache keys follow call form, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
A bounded cache retains up to maxsize recent entries and discards a least-recently-used entry when a new key needs space. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is treating maxsize as a limit on calls rather than stored keys. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Use a three-key trace with maxsize two and predict hits after every access.
For the maxsize and least-recently-used eviction chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on treating maxsize as a limit on calls rather than stored keys. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache(maxsize=2)
def f(x): return x*x
f(1); f(2); f(1); f(3); f(2)Explained result. The second access to 1 refreshes its recency; inserting 3 evicts 2, so the final f(2) is a miss. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: text analysis. Explain the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A bounded cache retains up to maxsize recent entries and discards a least-recently-used entry when a new key needs space.” Apply this procedure: Use a three-key trace with maxsize two and predict hits after every access. The expected mechanism is: The second access to 1 refreshes its recency; inserting 3 evicts 2, so the final f(2) is a miss. For the text analysis, add one near-miss that exposes treating maxsize as a limit on calls rather than stored keys. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: debug lab. Transfer the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A bounded cache retains up to maxsize recent entries and discards a least-recently-used entry when a new key needs space.” Apply this procedure: Use a three-key trace with maxsize two and predict hits after every access. The expected mechanism is: The second access to 1 refreshes its recency; inserting 3 evicts 2, so the final f(2) is a miss. For the debug lab, add one near-miss that exposes treating maxsize as a limit on calls rather than stored keys. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: revision planner. Predict the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A bounded cache retains up to maxsize recent entries and discards a least-recently-used entry when a new key needs space.” Apply this procedure: Use a three-key trace with maxsize two and predict hits after every access. The expected mechanism is: The second access to 1 refreshes its recency; inserting 3 evicts 2, so the final f(2) is a miss. For the revision planner, add one near-miss that exposes treating maxsize as a limit on calls rather than stored keys. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: route exercise. Contrast the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A bounded cache retains up to maxsize recent entries and discards a least-recently-used entry when a new key needs space.” Apply this procedure: Use a three-key trace with maxsize two and predict hits after every access. The expected mechanism is: The second access to 1 refreshes its recency; inserting 3 evicts 2, so the final f(2) is a miss. For the route exercise, add one near-miss that exposes treating maxsize as a limit on calls rather than stored keys. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers treating maxsize as a limit on calls rather than stored keys.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Use a three-key trace with maxsize two and predict hits after every access.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from maxsize and least-recently-used eviction?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing treating maxsize as a limit on calls rather than stored keys be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny revision planner with a pure function that scores topic and available minutes. Include one ordinary case, one boundary and one deliberate failure caused by treating maxsize as a limit on calls rather than stored keys. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: A bounded cache retains up to maxsize recent entries and discards a least-recently-used entry when a new key needs space. It shows a trace, not only a final value. The ordinary case should demonstrate “The second access to 1 refreshes its recency; inserting 3 evicts 2, so the final f(2) is a miss.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Use a three-key trace with maxsize two and predict hits after every access. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For maxsize and least-recently-used eviction, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
With maxsize=None, the LRU feature is disabled and old entries are never evicted automatically. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is using an unbounded cache on a long-running process with user-specific keys. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Estimate key cardinality and object retention, then choose a bound or an explicit lifecycle.
For the maxsize=None and unbounded growth chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on using an unbounded cache on a long-running process with user-specific keys. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache(maxsize=None)
def parse(code): return code.split('-')Explained result. Every distinct code remains cached until cache_clear or process end, so memory grows with unique inputs. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: revision planner. Transfer the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “With maxsize=None, the LRU feature is disabled and old entries are never evicted automatically.” Apply this procedure: Estimate key cardinality and object retention, then choose a bound or an explicit lifecycle. The expected mechanism is: Every distinct code remains cached until cache_clear or process end, so memory grows with unique inputs. For the revision planner, add one near-miss that exposes using an unbounded cache on a long-running process with user-specific keys. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: route exercise. Predict the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “With maxsize=None, the LRU feature is disabled and old entries are never evicted automatically.” Apply this procedure: Estimate key cardinality and object retention, then choose a bound or an explicit lifecycle. The expected mechanism is: Every distinct code remains cached until cache_clear or process end, so memory grows with unique inputs. For the route exercise, add one near-miss that exposes using an unbounded cache on a long-running process with user-specific keys. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: library lookup. Contrast the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “With maxsize=None, the LRU feature is disabled and old entries are never evicted automatically.” Apply this procedure: Estimate key cardinality and object retention, then choose a bound or an explicit lifecycle. The expected mechanism is: Every distinct code remains cached until cache_clear or process end, so memory grows with unique inputs. For the library lookup, add one near-miss that exposes using an unbounded cache on a long-running process with user-specific keys. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: science table. Stress-test the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “With maxsize=None, the LRU feature is disabled and old entries are never evicted automatically.” Apply this procedure: Estimate key cardinality and object retention, then choose a bound or an explicit lifecycle. The expected mechanism is: Every distinct code remains cached until cache_clear or process end, so memory grows with unique inputs. For the science table, add one near-miss that exposes using an unbounded cache on a long-running process with user-specific keys. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers using an unbounded cache on a long-running process with user-specific keys.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Estimate key cardinality and object retention, then choose a bound or an explicit lifecycle.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from maxsize=None and unbounded growth?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing using an unbounded cache on a long-running process with user-specific keys be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny route exercise with a recursive path count through a small grid. Include one ordinary case, one boundary and one deliberate failure caused by using an unbounded cache on a long-running process with user-specific keys. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: With maxsize=None, the LRU feature is disabled and old entries are never evicted automatically. It shows a trace, not only a final value. The ordinary case should demonstrate “Every distinct code remains cached until cache_clear or process end, so memory grows with unique inputs.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Estimate key cardinality and object retention, then choose a bound or an explicit lifecycle. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For maxsize=None and unbounded growth, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
With typed=True, arguments of different immediate types are cached separately, while some types may already be distinct under the default behaviour. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is assuming typed recursively distinguishes every element inside a container. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Test the exact immediate arguments and inspect currsize rather than inferring from type names.
For the typed changes selected key distinctions chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on assuming typed recursively distinguishes every element inside a container. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache(typed=True)
def identify(x): return type(x).__name__
identify(3); identify(3.0)Explained result. The integer and float calls use separate entries when typed=True. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: library lookup. Predict the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “With typed=True, arguments of different immediate types are cached separately, while some types may already be distinct under the default behaviour.” Apply this procedure: Test the exact immediate arguments and inspect currsize rather than inferring from type names. The expected mechanism is: The integer and float calls use separate entries when typed=True. For the library lookup, add one near-miss that exposes assuming typed recursively distinguishes every element inside a container. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: science table. Contrast the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “With typed=True, arguments of different immediate types are cached separately, while some types may already be distinct under the default behaviour.” Apply this procedure: Test the exact immediate arguments and inspect currsize rather than inferring from type names. The expected mechanism is: The integer and float calls use separate entries when typed=True. For the science table, add one near-miss that exposes assuming typed recursively distinguishes every element inside a container. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: quiz generator. Stress-test the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “With typed=True, arguments of different immediate types are cached separately, while some types may already be distinct under the default behaviour.” Apply this procedure: Test the exact immediate arguments and inspect currsize rather than inferring from type names. The expected mechanism is: The integer and float calls use separate entries when typed=True. For the quiz generator, add one near-miss that exposes assuming typed recursively distinguishes every element inside a container. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: budget model. Explain the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “With typed=True, arguments of different immediate types are cached separately, while some types may already be distinct under the default behaviour.” Apply this procedure: Test the exact immediate arguments and inspect currsize rather than inferring from type names. The expected mechanism is: The integer and float calls use separate entries when typed=True. For the budget model, add one near-miss that exposes assuming typed recursively distinguishes every element inside a container. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers assuming typed recursively distinguishes every element inside a container.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Test the exact immediate arguments and inspect currsize rather than inferring from type names.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from typed changes selected key distinctions?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing assuming typed recursively distinguishes every element inside a container be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny library lookup with a book-code formatter with repeated immutable inputs. Include one ordinary case, one boundary and one deliberate failure caused by assuming typed recursively distinguishes every element inside a container. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: With typed=True, arguments of different immediate types are cached separately, while some types may already be distinct under the default behaviour. It shows a trace, not only a final value. The ordinary case should demonstrate “The integer and float calls use separate entries when typed=True.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Test the exact immediate arguments and inspect currsize rather than inferring from type names. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For typed changes selected key distinctions, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
cache_info returns hits, misses, maxsize and currsize so a learner can evaluate the real call pattern. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is claiming a cache helps because the function feels faster once. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Reset, run a representative workload and interpret both hit rate and cost per miss.
For the cache_info supplies evidence chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on claiming a cache helps because the function feels faster once. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
before=f.cache_info()
f(1); f(1); f(2)
after=f.cache_info()Explained result. The difference should show two misses, one hit and a current size consistent with the distinct retained keys. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: quiz generator. Contrast the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_info returns hits, misses, maxsize and currsize so a learner can evaluate the real call pattern.” Apply this procedure: Reset, run a representative workload and interpret both hit rate and cost per miss. The expected mechanism is: The difference should show two misses, one hit and a current size consistent with the distinct retained keys. For the quiz generator, add one near-miss that exposes claiming a cache helps because the function feels faster once. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: budget model. Stress-test the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_info returns hits, misses, maxsize and currsize so a learner can evaluate the real call pattern.” Apply this procedure: Reset, run a representative workload and interpret both hit rate and cost per miss. The expected mechanism is: The difference should show two misses, one hit and a current size consistent with the distinct retained keys. For the budget model, add one near-miss that exposes claiming a cache helps because the function feels faster once. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: text analysis. Explain the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_info returns hits, misses, maxsize and currsize so a learner can evaluate the real call pattern.” Apply this procedure: Reset, run a representative workload and interpret both hit rate and cost per miss. The expected mechanism is: The difference should show two misses, one hit and a current size consistent with the distinct retained keys. For the text analysis, add one near-miss that exposes claiming a cache helps because the function feels faster once. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: debug lab. Transfer the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_info returns hits, misses, maxsize and currsize so a learner can evaluate the real call pattern.” Apply this procedure: Reset, run a representative workload and interpret both hit rate and cost per miss. The expected mechanism is: The difference should show two misses, one hit and a current size consistent with the distinct retained keys. For the debug lab, add one near-miss that exposes claiming a cache helps because the function feels faster once. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers claiming a cache helps because the function feels faster once.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Reset, run a representative workload and interpret both hit rate and cost per miss.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from cache_info supplies evidence?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing claiming a cache helps because the function feels faster once be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny science table with a conversion calculated from unit and fixed scale. Include one ordinary case, one boundary and one deliberate failure caused by claiming a cache helps because the function feels faster once. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: cache_info returns hits, misses, maxsize and currsize so a learner can evaluate the real call pattern. It shows a trace, not only a final value. The ordinary case should demonstrate “The difference should show two misses, one hit and a current size consistent with the distinct retained keys.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Reset, run a representative workload and interpret both hit rate and cost per miss. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For cache_info supplies evidence, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
cache_clear removes stored results and resets hit-and-miss counters for the wrapper. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is clearing one cache and assuming related external state is also reset. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Record external state separately, clear deliberately and prove the next repeated key is a miss.
For the cache_clear resets values and statistics chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on clearing one cache and assuming related external state is also reset. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
f(7); f(7)
f.cache_clear()
f(7)Explained result. The call after cache_clear executes the function body again and starts a fresh statistics window. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: text analysis. Stress-test the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_clear removes stored results and resets hit-and-miss counters for the wrapper.” Apply this procedure: Record external state separately, clear deliberately and prove the next repeated key is a miss. The expected mechanism is: The call after cache_clear executes the function body again and starts a fresh statistics window. For the text analysis, add one near-miss that exposes clearing one cache and assuming related external state is also reset. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: debug lab. Explain the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_clear removes stored results and resets hit-and-miss counters for the wrapper.” Apply this procedure: Record external state separately, clear deliberately and prove the next repeated key is a miss. The expected mechanism is: The call after cache_clear executes the function body again and starts a fresh statistics window. For the debug lab, add one near-miss that exposes clearing one cache and assuming related external state is also reset. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: revision planner. Transfer the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_clear removes stored results and resets hit-and-miss counters for the wrapper.” Apply this procedure: Record external state separately, clear deliberately and prove the next repeated key is a miss. The expected mechanism is: The call after cache_clear executes the function body again and starts a fresh statistics window. For the revision planner, add one near-miss that exposes clearing one cache and assuming related external state is also reset. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: route exercise. Predict the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_clear removes stored results and resets hit-and-miss counters for the wrapper.” Apply this procedure: Record external state separately, clear deliberately and prove the next repeated key is a miss. The expected mechanism is: The call after cache_clear executes the function body again and starts a fresh statistics window. For the route exercise, add one near-miss that exposes clearing one cache and assuming related external state is also reset. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers clearing one cache and assuming related external state is also reset.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Record external state separately, clear deliberately and prove the next repeated key is a miss.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from cache_clear resets values and statistics?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing clearing one cache and assuming related external state is also reset be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny quiz generator with a deterministic question chosen from topic and level. Include one ordinary case, one boundary and one deliberate failure caused by clearing one cache and assuming related external state is also reset. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: cache_clear removes stored results and resets hit-and-miss counters for the wrapper. It shows a trace, not only a final value. The ordinary case should demonstrate “The call after cache_clear executes the function body again and starts a fresh statistics window.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Record external state separately, clear deliberately and prove the next repeated key is a miss. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For cache_clear resets values and statistics, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
cache_parameters returns a new dictionary describing maxsize and typed; mutating that dictionary does not reconfigure the wrapper. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is editing the returned dictionary and expecting the live cache to change. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Treat configuration as decoration-time policy and redecorate when the policy must change.
For the cache_parameters reports configuration chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on editing the returned dictionary and expecting the live cache to change. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
params=f.cache_parameters()
params['maxsize']=999Explained result. The local dictionary changes, but the wrapper keeps its original maxsize. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: revision planner. Explain the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_parameters returns a new dictionary describing maxsize and typed; mutating that dictionary does not reconfigure the wrapper.” Apply this procedure: Treat configuration as decoration-time policy and redecorate when the policy must change. The expected mechanism is: The local dictionary changes, but the wrapper keeps its original maxsize. For the revision planner, add one near-miss that exposes editing the returned dictionary and expecting the live cache to change. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: route exercise. Transfer the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_parameters returns a new dictionary describing maxsize and typed; mutating that dictionary does not reconfigure the wrapper.” Apply this procedure: Treat configuration as decoration-time policy and redecorate when the policy must change. The expected mechanism is: The local dictionary changes, but the wrapper keeps its original maxsize. For the route exercise, add one near-miss that exposes editing the returned dictionary and expecting the live cache to change. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: library lookup. Predict the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_parameters returns a new dictionary describing maxsize and typed; mutating that dictionary does not reconfigure the wrapper.” Apply this procedure: Treat configuration as decoration-time policy and redecorate when the policy must change. The expected mechanism is: The local dictionary changes, but the wrapper keeps its original maxsize. For the library lookup, add one near-miss that exposes editing the returned dictionary and expecting the live cache to change. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: science table. Contrast the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “cache_parameters returns a new dictionary describing maxsize and typed; mutating that dictionary does not reconfigure the wrapper.” Apply this procedure: Treat configuration as decoration-time policy and redecorate when the policy must change. The expected mechanism is: The local dictionary changes, but the wrapper keeps its original maxsize. For the science table, add one near-miss that exposes editing the returned dictionary and expecting the live cache to change. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers editing the returned dictionary and expecting the live cache to change.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Treat configuration as decoration-time policy and redecorate when the policy must change.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from cache_parameters reports configuration?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing editing the returned dictionary and expecting the live cache to change be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny budget model with a repeated tax calculation from immutable rates. Include one ordinary case, one boundary and one deliberate failure caused by editing the returned dictionary and expecting the live cache to change. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: cache_parameters returns a new dictionary describing maxsize and typed; mutating that dictionary does not reconfigure the wrapper. It shows a trace, not only a final value. The ordinary case should demonstrate “The local dictionary changes, but the wrapper keeps its original maxsize.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Treat configuration as decoration-time policy and redecorate when the policy must change. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For cache_parameters reports configuration, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
functools.cache is a simpler unbounded memoizing wrapper, equivalent in purpose to lru_cache with maxsize=None. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is choosing cache because its name sounds safer than lru_cache. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Compare key cardinality and lifecycle first; select the spelling that communicates the intended policy.
For the functools.cache is the unbounded form chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on choosing cache because its name sounds safer than lru_cache. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
from functools import cache
@cache
def fib(n): return n if n<2 else fib(n-1)+fib(n-2)Explained result. The recursion reuses completed subproblems without eviction, which is suitable only while the input domain stays controlled. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: library lookup. Transfer the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “functools.cache is a simpler unbounded memoizing wrapper, equivalent in purpose to lru_cache with maxsize=None.” Apply this procedure: Compare key cardinality and lifecycle first; select the spelling that communicates the intended policy. The expected mechanism is: The recursion reuses completed subproblems without eviction, which is suitable only while the input domain stays controlled. For the library lookup, add one near-miss that exposes choosing cache because its name sounds safer than lru_cache. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: science table. Predict the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “functools.cache is a simpler unbounded memoizing wrapper, equivalent in purpose to lru_cache with maxsize=None.” Apply this procedure: Compare key cardinality and lifecycle first; select the spelling that communicates the intended policy. The expected mechanism is: The recursion reuses completed subproblems without eviction, which is suitable only while the input domain stays controlled. For the science table, add one near-miss that exposes choosing cache because its name sounds safer than lru_cache. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: quiz generator. Contrast the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “functools.cache is a simpler unbounded memoizing wrapper, equivalent in purpose to lru_cache with maxsize=None.” Apply this procedure: Compare key cardinality and lifecycle first; select the spelling that communicates the intended policy. The expected mechanism is: The recursion reuses completed subproblems without eviction, which is suitable only while the input domain stays controlled. For the quiz generator, add one near-miss that exposes choosing cache because its name sounds safer than lru_cache. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: budget model. Stress-test the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “functools.cache is a simpler unbounded memoizing wrapper, equivalent in purpose to lru_cache with maxsize=None.” Apply this procedure: Compare key cardinality and lifecycle first; select the spelling that communicates the intended policy. The expected mechanism is: The recursion reuses completed subproblems without eviction, which is suitable only while the input domain stays controlled. For the budget model, add one near-miss that exposes choosing cache because its name sounds safer than lru_cache. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers choosing cache because its name sounds safer than lru_cache.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Compare key cardinality and lifecycle first; select the spelling that communicates the intended policy.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from functools.cache is the unbounded form?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing choosing cache because its name sounds safer than lru_cache be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny text analysis with a word feature function called across many sentences. Include one ordinary case, one boundary and one deliberate failure caused by choosing cache because its name sounds safer than lru_cache. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: functools.cache is a simpler unbounded memoizing wrapper, equivalent in purpose to lru_cache with maxsize=None. It shows a trace, not only a final value. The ordinary case should demonstrate “The recursion reuses completed subproblems without eviction, which is suitable only while the input domain stays controlled.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Compare key cardinality and lifecycle first; select the spelling that communicates the intended policy. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For functools.cache is the unbounded form, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
When a cached function is an instance method, the instance participates in the key and can be retained by the cache. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is expecting entries to be shared solely by the visible method arguments. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Create two instances, call the same value and inspect misses and object lifetime.
For the Methods include self in the key chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on expecting entries to be shared solely by the visible method arguments. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
class Scale:
@lru_cache
def apply(self,x): return self.factor*xExplained result. Calls on two Scale instances normally occupy different keys because self differs. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: quiz generator. Predict the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “When a cached function is an instance method, the instance participates in the key and can be retained by the cache.” Apply this procedure: Create two instances, call the same value and inspect misses and object lifetime. The expected mechanism is: Calls on two Scale instances normally occupy different keys because self differs. For the quiz generator, add one near-miss that exposes expecting entries to be shared solely by the visible method arguments. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: budget model. Contrast the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “When a cached function is an instance method, the instance participates in the key and can be retained by the cache.” Apply this procedure: Create two instances, call the same value and inspect misses and object lifetime. The expected mechanism is: Calls on two Scale instances normally occupy different keys because self differs. For the budget model, add one near-miss that exposes expecting entries to be shared solely by the visible method arguments. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: text analysis. Stress-test the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “When a cached function is an instance method, the instance participates in the key and can be retained by the cache.” Apply this procedure: Create two instances, call the same value and inspect misses and object lifetime. The expected mechanism is: Calls on two Scale instances normally occupy different keys because self differs. For the text analysis, add one near-miss that exposes expecting entries to be shared solely by the visible method arguments. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: debug lab. Explain the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “When a cached function is an instance method, the instance participates in the key and can be retained by the cache.” Apply this procedure: Create two instances, call the same value and inspect misses and object lifetime. The expected mechanism is: Calls on two Scale instances normally occupy different keys because self differs. For the debug lab, add one near-miss that exposes expecting entries to be shared solely by the visible method arguments. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers expecting entries to be shared solely by the visible method arguments.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Create two instances, call the same value and inspect misses and object lifetime.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Methods include self in the key?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing expecting entries to be shared solely by the visible method arguments be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny debug lab with a counter proving which calls execute and which return cached values. Include one ordinary case, one boundary and one deliberate failure caused by expecting entries to be shared solely by the visible method arguments. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: When a cached function is an instance method, the instance participates in the key and can be retained by the cache. It shows a trace, not only a final value. The ordinary case should demonstrate “Calls on two Scale instances normally occupy different keys because self differs.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Create two instances, call the same value and inspect misses and object lifetime. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Methods include self in the key, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Memoization can turn overlapping recursive subproblems into one computation per distinct state when the recurrence is pure. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is caching a recursion without proving the state completely determines the answer. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Define the recurrence, base cases and complete immutable state tuple before decorating.
For the Recursive dynamic programming chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on caching a recursion without proving the state completely determines the answer. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache(None)
def ways(r,c):
if r==0 or c==0: return 1
return ways(r-1,c)+ways(r,c-1)Explained result. Each coordinate pair is solved once and later recursive branches reuse it. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: text analysis. Contrast the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Memoization can turn overlapping recursive subproblems into one computation per distinct state when the recurrence is pure.” Apply this procedure: Define the recurrence, base cases and complete immutable state tuple before decorating. The expected mechanism is: Each coordinate pair is solved once and later recursive branches reuse it. For the text analysis, add one near-miss that exposes caching a recursion without proving the state completely determines the answer. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: debug lab. Stress-test the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Memoization can turn overlapping recursive subproblems into one computation per distinct state when the recurrence is pure.” Apply this procedure: Define the recurrence, base cases and complete immutable state tuple before decorating. The expected mechanism is: Each coordinate pair is solved once and later recursive branches reuse it. For the debug lab, add one near-miss that exposes caching a recursion without proving the state completely determines the answer. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: revision planner. Explain the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Memoization can turn overlapping recursive subproblems into one computation per distinct state when the recurrence is pure.” Apply this procedure: Define the recurrence, base cases and complete immutable state tuple before decorating. The expected mechanism is: Each coordinate pair is solved once and later recursive branches reuse it. For the revision planner, add one near-miss that exposes caching a recursion without proving the state completely determines the answer. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: route exercise. Transfer the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Memoization can turn overlapping recursive subproblems into one computation per distinct state when the recurrence is pure.” Apply this procedure: Define the recurrence, base cases and complete immutable state tuple before decorating. The expected mechanism is: Each coordinate pair is solved once and later recursive branches reuse it. For the route exercise, add one near-miss that exposes caching a recursion without proving the state completely determines the answer. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers caching a recursion without proving the state completely determines the answer.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Define the recurrence, base cases and complete immutable state tuple before decorating.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Recursive dynamic programming?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing caching a recursion without proving the state completely determines the answer be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny revision planner with a pure function that scores topic and available minutes. Include one ordinary case, one boundary and one deliberate failure caused by caching a recursion without proving the state completely determines the answer. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Memoization can turn overlapping recursive subproblems into one computation per distinct state when the recurrence is pure. It shows a trace, not only a final value. The ordinary case should demonstrate “Each coordinate pair is solved once and later recursive branches reuse it.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Define the recurrence, base cases and complete immutable state tuple before decorating. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Recursive dynamic programming, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
A cached result is sound only while the key captures every dependency that should change the answer. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is caching a function that reads a mutable global, clock, file or environment value. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. List all dependencies and either include a version in the key or keep the function uncached.
For the Purity and hidden dependencies chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on caching a function that reads a mutable global, clock, file or environment value. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
rate=1.09
@lru_cache
def convert(x): return x*rateExplained result. Changing rate does not invalidate convert(10), so the cache can return a stale result. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: revision planner. Stress-test the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A cached result is sound only while the key captures every dependency that should change the answer.” Apply this procedure: List all dependencies and either include a version in the key or keep the function uncached. The expected mechanism is: Changing rate does not invalidate convert(10), so the cache can return a stale result. For the revision planner, add one near-miss that exposes caching a function that reads a mutable global, clock, file or environment value. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: route exercise. Explain the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A cached result is sound only while the key captures every dependency that should change the answer.” Apply this procedure: List all dependencies and either include a version in the key or keep the function uncached. The expected mechanism is: Changing rate does not invalidate convert(10), so the cache can return a stale result. For the route exercise, add one near-miss that exposes caching a function that reads a mutable global, clock, file or environment value. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: library lookup. Transfer the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A cached result is sound only while the key captures every dependency that should change the answer.” Apply this procedure: List all dependencies and either include a version in the key or keep the function uncached. The expected mechanism is: Changing rate does not invalidate convert(10), so the cache can return a stale result. For the library lookup, add one near-miss that exposes caching a function that reads a mutable global, clock, file or environment value. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: science table. Predict the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A cached result is sound only while the key captures every dependency that should change the answer.” Apply this procedure: List all dependencies and either include a version in the key or keep the function uncached. The expected mechanism is: Changing rate does not invalidate convert(10), so the cache can return a stale result. For the science table, add one near-miss that exposes caching a function that reads a mutable global, clock, file or environment value. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers caching a function that reads a mutable global, clock, file or environment value.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “List all dependencies and either include a version in the key or keep the function uncached.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Purity and hidden dependencies?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing caching a function that reads a mutable global, clock, file or environment value be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny route exercise with a recursive path count through a small grid. Include one ordinary case, one boundary and one deliberate failure caused by caching a function that reads a mutable global, clock, file or environment value. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: A cached result is sound only while the key captures every dependency that should change the answer. It shows a trace, not only a final value. The ordinary case should demonstrate “Changing rate does not invalidate convert(10), so the cache can return a stale result.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: List all dependencies and either include a version in the key or keep the function uncached. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Purity and hidden dependencies, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
The cache returns the stored object itself, so a caller can mutate a cached list or dictionary and affect later callers. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is believing cached results are cloned on every hit. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Prefer immutable results or copy at a clearly documented boundary, then test identity.
For the Mutable return values remain shared chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on believing cached results are cloned on every hit. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache
def labels(n): return [str(i) for i in range(n)]
a=labels(2); a.append('x')Explained result. A later labels(2) sees the same mutated list object unless the design prevents or copies mutation. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: library lookup. Explain the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The cache returns the stored object itself, so a caller can mutate a cached list or dictionary and affect later callers.” Apply this procedure: Prefer immutable results or copy at a clearly documented boundary, then test identity. The expected mechanism is: A later labels(2) sees the same mutated list object unless the design prevents or copies mutation. For the library lookup, add one near-miss that exposes believing cached results are cloned on every hit. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: science table. Transfer the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The cache returns the stored object itself, so a caller can mutate a cached list or dictionary and affect later callers.” Apply this procedure: Prefer immutable results or copy at a clearly documented boundary, then test identity. The expected mechanism is: A later labels(2) sees the same mutated list object unless the design prevents or copies mutation. For the science table, add one near-miss that exposes believing cached results are cloned on every hit. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: quiz generator. Predict the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The cache returns the stored object itself, so a caller can mutate a cached list or dictionary and affect later callers.” Apply this procedure: Prefer immutable results or copy at a clearly documented boundary, then test identity. The expected mechanism is: A later labels(2) sees the same mutated list object unless the design prevents or copies mutation. For the quiz generator, add one near-miss that exposes believing cached results are cloned on every hit. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: budget model. Contrast the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The cache returns the stored object itself, so a caller can mutate a cached list or dictionary and affect later callers.” Apply this procedure: Prefer immutable results or copy at a clearly documented boundary, then test identity. The expected mechanism is: A later labels(2) sees the same mutated list object unless the design prevents or copies mutation. For the budget model, add one near-miss that exposes believing cached results are cloned on every hit. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers believing cached results are cloned on every hit.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Prefer immutable results or copy at a clearly documented boundary, then test identity.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Mutable return values remain shared?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing believing cached results are cloned on every hit be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny library lookup with a book-code formatter with repeated immutable inputs. Include one ordinary case, one boundary and one deliberate failure caused by believing cached results are cloned on every hit. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: The cache returns the stored object itself, so a caller can mutate a cached list or dictionary and affect later callers. It shows a trace, not only a final value. The ordinary case should demonstrate “A later labels(2) sees the same mutated list object unless the design prevents or copies mutation.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Prefer immutable results or copy at a clearly documented boundary, then test identity. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Mutable return values remain shared, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
If the wrapped call raises, no normal return value is stored for that call, so a later identical call invokes the body again. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is expecting one failure to become a permanent cached failure. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Count executions around a deliberately raised exception and separate retry policy from memoization.
For the Exceptions are not successful cached results chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on expecting one failure to become a permanent cached failure. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache
def positive(n):
if n<0: raise ValueError('negative')
return nExplained result. Two positive(-1) attempts raise twice because neither call completed with a cacheable return value. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: quiz generator. Transfer the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “If the wrapped call raises, no normal return value is stored for that call, so a later identical call invokes the body again.” Apply this procedure: Count executions around a deliberately raised exception and separate retry policy from memoization. The expected mechanism is: Two positive(-1) attempts raise twice because neither call completed with a cacheable return value. For the quiz generator, add one near-miss that exposes expecting one failure to become a permanent cached failure. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: budget model. Predict the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “If the wrapped call raises, no normal return value is stored for that call, so a later identical call invokes the body again.” Apply this procedure: Count executions around a deliberately raised exception and separate retry policy from memoization. The expected mechanism is: Two positive(-1) attempts raise twice because neither call completed with a cacheable return value. For the budget model, add one near-miss that exposes expecting one failure to become a permanent cached failure. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: text analysis. Contrast the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “If the wrapped call raises, no normal return value is stored for that call, so a later identical call invokes the body again.” Apply this procedure: Count executions around a deliberately raised exception and separate retry policy from memoization. The expected mechanism is: Two positive(-1) attempts raise twice because neither call completed with a cacheable return value. For the text analysis, add one near-miss that exposes expecting one failure to become a permanent cached failure. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: debug lab. Stress-test the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “If the wrapped call raises, no normal return value is stored for that call, so a later identical call invokes the body again.” Apply this procedure: Count executions around a deliberately raised exception and separate retry policy from memoization. The expected mechanism is: Two positive(-1) attempts raise twice because neither call completed with a cacheable return value. For the debug lab, add one near-miss that exposes expecting one failure to become a permanent cached failure. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers expecting one failure to become a permanent cached failure.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Count executions around a deliberately raised exception and separate retry policy from memoization.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Exceptions are not successful cached results?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing expecting one failure to become a permanent cached failure be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny science table with a conversion calculated from unit and fixed scale. Include one ordinary case, one boundary and one deliberate failure caused by expecting one failure to become a permanent cached failure. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: If the wrapped call raises, no normal return value is stored for that call, so a later identical call invokes the body again. It shows a trace, not only a final value. The ordinary case should demonstrate “Two positive(-1) attempts raise twice because neither call completed with a cacheable return value.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Count executions around a deliberately raised exception and separate retry policy from memoization. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Exceptions are not successful cached results, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
The cache data structure is threadsafe, but another thread can call the underlying function again before the first result is stored. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is equating coherent cache state with exactly-once execution. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Use an idempotent function or a stronger single-flight design when duplicate in-flight work is unacceptable.
For the Concurrent calls may duplicate work chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on equating coherent cache state with exactly-once execution. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache
def slow(key):
return expensive_lookup(key)Explained result. Two overlapping misses for the same key may both run expensive_lookup even though later calls hit one cached result. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: text analysis. Predict the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The cache data structure is threadsafe, but another thread can call the underlying function again before the first result is stored.” Apply this procedure: Use an idempotent function or a stronger single-flight design when duplicate in-flight work is unacceptable. The expected mechanism is: Two overlapping misses for the same key may both run expensive_lookup even though later calls hit one cached result. For the text analysis, add one near-miss that exposes equating coherent cache state with exactly-once execution. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: debug lab. Contrast the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The cache data structure is threadsafe, but another thread can call the underlying function again before the first result is stored.” Apply this procedure: Use an idempotent function or a stronger single-flight design when duplicate in-flight work is unacceptable. The expected mechanism is: Two overlapping misses for the same key may both run expensive_lookup even though later calls hit one cached result. For the debug lab, add one near-miss that exposes equating coherent cache state with exactly-once execution. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: revision planner. Stress-test the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The cache data structure is threadsafe, but another thread can call the underlying function again before the first result is stored.” Apply this procedure: Use an idempotent function or a stronger single-flight design when duplicate in-flight work is unacceptable. The expected mechanism is: Two overlapping misses for the same key may both run expensive_lookup even though later calls hit one cached result. For the revision planner, add one near-miss that exposes equating coherent cache state with exactly-once execution. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: route exercise. Explain the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The cache data structure is threadsafe, but another thread can call the underlying function again before the first result is stored.” Apply this procedure: Use an idempotent function or a stronger single-flight design when duplicate in-flight work is unacceptable. The expected mechanism is: Two overlapping misses for the same key may both run expensive_lookup even though later calls hit one cached result. For the route exercise, add one near-miss that exposes equating coherent cache state with exactly-once execution. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers equating coherent cache state with exactly-once execution.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Use an idempotent function or a stronger single-flight design when duplicate in-flight work is unacceptable.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Concurrent calls may duplicate work?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing equating coherent cache state with exactly-once execution be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny quiz generator with a deterministic question chosen from topic and level. Include one ordinary case, one boundary and one deliberate failure caused by equating coherent cache state with exactly-once execution. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: The cache data structure is threadsafe, but another thread can call the underlying function again before the first result is stored. It shows a trace, not only a final value. The ordinary case should demonstrate “Two overlapping misses for the same key may both run expensive_lookup even though later calls hit one cached result.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Use an idempotent function or a stronger single-flight design when duplicate in-flight work is unacceptable. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Concurrent calls may duplicate work, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Caching a coroutine function stores coroutine objects rather than completed await results, which conflicts with one-shot coroutine execution. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is decorating async def and expecting reusable resolved values. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Cache stable data below the async boundary or use an async-aware cache with explicit concurrency rules.
For the Coroutine functions are a poor fit chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on decorating async def and expecting reusable resolved values. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@lru_cache
async def fetch(code): return await remote(code)Explained result. Repeated calls can retrieve the same already-awaited coroutine object, so ordinary lru_cache is not an async result cache. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: revision planner. Contrast the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Caching a coroutine function stores coroutine objects rather than completed await results, which conflicts with one-shot coroutine execution.” Apply this procedure: Cache stable data below the async boundary or use an async-aware cache with explicit concurrency rules. The expected mechanism is: Repeated calls can retrieve the same already-awaited coroutine object, so ordinary lru_cache is not an async result cache. For the revision planner, add one near-miss that exposes decorating async def and expecting reusable resolved values. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: route exercise. Stress-test the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Caching a coroutine function stores coroutine objects rather than completed await results, which conflicts with one-shot coroutine execution.” Apply this procedure: Cache stable data below the async boundary or use an async-aware cache with explicit concurrency rules. The expected mechanism is: Repeated calls can retrieve the same already-awaited coroutine object, so ordinary lru_cache is not an async result cache. For the route exercise, add one near-miss that exposes decorating async def and expecting reusable resolved values. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: library lookup. Explain the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Caching a coroutine function stores coroutine objects rather than completed await results, which conflicts with one-shot coroutine execution.” Apply this procedure: Cache stable data below the async boundary or use an async-aware cache with explicit concurrency rules. The expected mechanism is: Repeated calls can retrieve the same already-awaited coroutine object, so ordinary lru_cache is not an async result cache. For the library lookup, add one near-miss that exposes decorating async def and expecting reusable resolved values. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: science table. Transfer the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Caching a coroutine function stores coroutine objects rather than completed await results, which conflicts with one-shot coroutine execution.” Apply this procedure: Cache stable data below the async boundary or use an async-aware cache with explicit concurrency rules. The expected mechanism is: Repeated calls can retrieve the same already-awaited coroutine object, so ordinary lru_cache is not an async result cache. For the science table, add one near-miss that exposes decorating async def and expecting reusable resolved values. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers decorating async def and expecting reusable resolved values.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Cache stable data below the async boundary or use an async-aware cache with explicit concurrency rules.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Coroutine functions are a poor fit?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing decorating async def and expecting reusable resolved values be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny budget model with a repeated tax calculation from immutable rates. Include one ordinary case, one boundary and one deliberate failure caused by decorating async def and expecting reusable resolved values. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Caching a coroutine function stores coroutine objects rather than completed await results, which conflicts with one-shot coroutine execution. It shows a trace, not only a final value. The ordinary case should demonstrate “Repeated calls can retrieve the same already-awaited coroutine object, so ordinary lru_cache is not an async result cache.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Cache stable data below the async boundary or use an async-aware cache with explicit concurrency rules. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Coroutine functions are a poor fit, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Keys and return values remain strongly referenced until eviction or clearing, so caching can extend object lifetimes. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is measuring only execution time while ignoring retained inputs and results. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Observe currsize, estimate object weight and test garbage collection after eviction or clearing.
For the Object lifetime and memory retention chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on measuring only execution time while ignoring retained inputs and results. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
large=build_large_key()
f(large)
del largeExplained result. The cache key can keep the object reachable even after the local name is deleted. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: library lookup. Stress-test the rule using a book-code formatter with repeated immutable inputs. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Keys and return values remain strongly referenced until eviction or clearing, so caching can extend object lifetimes.” Apply this procedure: Observe currsize, estimate object weight and test garbage collection after eviction or clearing. The expected mechanism is: The cache key can keep the object reachable even after the local name is deleted. For the library lookup, add one near-miss that exposes measuring only execution time while ignoring retained inputs and results. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: science table. Explain the rule using a conversion calculated from unit and fixed scale. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Keys and return values remain strongly referenced until eviction or clearing, so caching can extend object lifetimes.” Apply this procedure: Observe currsize, estimate object weight and test garbage collection after eviction or clearing. The expected mechanism is: The cache key can keep the object reachable even after the local name is deleted. For the science table, add one near-miss that exposes measuring only execution time while ignoring retained inputs and results. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: quiz generator. Transfer the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Keys and return values remain strongly referenced until eviction or clearing, so caching can extend object lifetimes.” Apply this procedure: Observe currsize, estimate object weight and test garbage collection after eviction or clearing. The expected mechanism is: The cache key can keep the object reachable even after the local name is deleted. For the quiz generator, add one near-miss that exposes measuring only execution time while ignoring retained inputs and results. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: budget model. Predict the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Keys and return values remain strongly referenced until eviction or clearing, so caching can extend object lifetimes.” Apply this procedure: Observe currsize, estimate object weight and test garbage collection after eviction or clearing. The expected mechanism is: The cache key can keep the object reachable even after the local name is deleted. For the budget model, add one near-miss that exposes measuring only execution time while ignoring retained inputs and results. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers measuring only execution time while ignoring retained inputs and results.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Observe currsize, estimate object weight and test garbage collection after eviction or clearing.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Object lifetime and memory retention?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing measuring only execution time while ignoring retained inputs and results be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny text analysis with a word feature function called across many sentences. Include one ordinary case, one boundary and one deliberate failure caused by measuring only execution time while ignoring retained inputs and results. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Keys and return values remain strongly referenced until eviction or clearing, so caching can extend object lifetimes. It shows a trace, not only a final value. The ordinary case should demonstrate “The cache key can keep the object reachable even after the local name is deleted.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Observe currsize, estimate object weight and test garbage collection after eviction or clearing. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Object lifetime and memory retention, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
CHAPTER 19 OF 20 . Transfer with judgment
19. Invalidation and TTL are separate policies
lru_cache provides size-based eviction and manual clearing, not per-entry time-to-live or dependency-aware invalidation. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is presenting LRU recency as proof that data is fresh. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Define the freshness contract and use versioned keys, scheduled clearing or a cache designed for TTL.
For the Invalidation and TTL are separate policies chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on presenting LRU recency as proof that data is fresh. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
value = lookup(student_id, data_version)Explained result. Including a data version makes changed source state produce a new key, while old entries still need lifecycle management. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: quiz generator. Explain the rule using a deterministic question chosen from topic and level. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “lru_cache provides size-based eviction and manual clearing, not per-entry time-to-live or dependency-aware invalidation.” Apply this procedure: Define the freshness contract and use versioned keys, scheduled clearing or a cache designed for TTL. The expected mechanism is: Including a data version makes changed source state produce a new key, while old entries still need lifecycle management. For the quiz generator, add one near-miss that exposes presenting LRU recency as proof that data is fresh. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: budget model. Transfer the rule using a repeated tax calculation from immutable rates. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “lru_cache provides size-based eviction and manual clearing, not per-entry time-to-live or dependency-aware invalidation.” Apply this procedure: Define the freshness contract and use versioned keys, scheduled clearing or a cache designed for TTL. The expected mechanism is: Including a data version makes changed source state produce a new key, while old entries still need lifecycle management. For the budget model, add one near-miss that exposes presenting LRU recency as proof that data is fresh. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: text analysis. Predict the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “lru_cache provides size-based eviction and manual clearing, not per-entry time-to-live or dependency-aware invalidation.” Apply this procedure: Define the freshness contract and use versioned keys, scheduled clearing or a cache designed for TTL. The expected mechanism is: Including a data version makes changed source state produce a new key, while old entries still need lifecycle management. For the text analysis, add one near-miss that exposes presenting LRU recency as proof that data is fresh. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: debug lab. Contrast the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “lru_cache provides size-based eviction and manual clearing, not per-entry time-to-live or dependency-aware invalidation.” Apply this procedure: Define the freshness contract and use versioned keys, scheduled clearing or a cache designed for TTL. The expected mechanism is: Including a data version makes changed source state produce a new key, while old entries still need lifecycle management. For the debug lab, add one near-miss that exposes presenting LRU recency as proof that data is fresh. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers presenting LRU recency as proof that data is fresh.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Define the freshness contract and use versioned keys, scheduled clearing or a cache designed for TTL.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from Invalidation and TTL are separate policies?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing presenting LRU recency as proof that data is fresh be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny debug lab with a counter proving which calls execute and which return cached values. Include one ordinary case, one boundary and one deliberate failure caused by presenting LRU recency as proof that data is fresh. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: lru_cache provides size-based eviction and manual clearing, not per-entry time-to-live or dependency-aware invalidation. It shows a trace, not only a final value. The ordinary case should demonstrate “Including a data version makes changed source state produce a new key, while old entries still need lifecycle management.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Define the freshness contract and use versioned keys, scheduled clearing or a cache designed for TTL. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Invalidation and TTL are separate policies, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Caching is worthwhile when repeated keys are common, misses are meaningfully expensive, results are stable and retained memory is acceptable. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is decorating every small helper before profiling. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Benchmark representative uncached work, warm and cold cache paths, hit rate and memory, then keep a removal test.
For the A measurement-led decision framework chapter on Python functools.lru_cache, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on decorating every small helper before profiling. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
f.cache_clear()
run_workload()
print(f.cache_info())Explained result. The evidence must connect workload repetition and miss cost to a justified maxsize, not merely show that hits exist. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: text analysis. Transfer the rule using a word feature function called across many sentences. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Caching is worthwhile when repeated keys are common, misses are meaningfully expensive, results are stable and retained memory is acceptable.” Apply this procedure: Benchmark representative uncached work, warm and cold cache paths, hit rate and memory, then keep a removal test. The expected mechanism is: The evidence must connect workload repetition and miss cost to a justified maxsize, not merely show that hits exist. For the text analysis, add one near-miss that exposes decorating every small helper before profiling. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: debug lab. Predict the rule using a counter proving which calls execute and which return cached values. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Caching is worthwhile when repeated keys are common, misses are meaningfully expensive, results are stable and retained memory is acceptable.” Apply this procedure: Benchmark representative uncached work, warm and cold cache paths, hit rate and memory, then keep a removal test. The expected mechanism is: The evidence must connect workload repetition and miss cost to a justified maxsize, not merely show that hits exist. For the debug lab, add one near-miss that exposes decorating every small helper before profiling. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: revision planner. Contrast the rule using a pure function that scores topic and available minutes. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Caching is worthwhile when repeated keys are common, misses are meaningfully expensive, results are stable and retained memory is acceptable.” Apply this procedure: Benchmark representative uncached work, warm and cold cache paths, hit rate and memory, then keep a removal test. The expected mechanism is: The evidence must connect workload repetition and miss cost to a justified maxsize, not merely show that hits exist. For the revision planner, add one near-miss that exposes decorating every small helper before profiling. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: route exercise. Stress-test the rule using a recursive path count through a small grid. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Caching is worthwhile when repeated keys are common, misses are meaningfully expensive, results are stable and retained memory is acceptable.” Apply this procedure: Benchmark representative uncached work, warm and cold cache paths, hit rate and memory, then keep a removal test. The expected mechanism is: The evidence must connect workload repetition and miss cost to a justified maxsize, not merely show that hits exist. For the route exercise, add one near-miss that exposes decorating every small helper before profiling. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers decorating every small helper before profiling.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Benchmark representative uncached work, warm and cold cache paths, hit rate and memory, then keep a removal test.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python functools.lru_cache syntax. For this chapter, useful prompts are: “What did you expect from A measurement-led decision framework?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing decorating every small helper before profiling be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny revision planner with a pure function that scores topic and available minutes. Include one ordinary case, one boundary and one deliberate failure caused by decorating every small helper before profiling. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Caching is worthwhile when repeated keys are common, misses are meaningfully expensive, results are stable and retained memory is acceptable. It shows a trace, not only a final value. The ordinary case should demonstrate “The evidence must connect workload repetition and miss cost to a justified maxsize, not merely show that hits exist.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Benchmark representative uncached work, warm and cold cache paths, hit rate and memory, then keep a removal test. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For A measurement-led decision framework, separate the documented Python functools.lru_cache mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Parent guide: choose the next useful step
Start with evidence, not a label such as careless. Ask for one prediction and one trace. If the first transition is wrong, rebuild the model. If the model is sound but syntax fails, practise reference use. If routine cases are correct but boundaries fail, vary ties, defaults, unsupported inputs, ownership or missing paths. If explanations transfer, move to a small project.
Keep a weekly record with four lines: concept, prediction, observed difference and next test. Stop when fatigue replaces reasoning. A smaller case tomorrow is more useful than another hour of copying tonight.
Seek specialist help when cause and effect remain invisible after examples are reduced, when accessibility or data-loss implications are unclear, or when an important repository, database or application state may be at risk. Good support should make the learner’s reasoning more independent.
Capstone practice with explained routes
1. revision planner: model, boundary and recovery
Create a small revision planner using a pure function that scores topic and available minutes. Combine “The wrapper-and-key mental model” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: lru_cache returns a wrapper that maps argument-derived keys to completed return values and tracks recent use for eviction. Apply: Count actual function-body executions and wrapper calls separately, then inspect cache_info. Verify: Calling square(3) twice prints once: the second call finds the same key and reuses 9. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
2. route exercise: model, boundary and recovery
Create a small route exercise using a recursive path count through a small grid. Combine “maxsize and least-recently-used eviction” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: A bounded cache retains up to maxsize recent entries and discards a least-recently-used entry when a new key needs space. Apply: Use a three-key trace with maxsize two and predict hits after every access. Verify: The second access to 1 refreshes its recency; inserting 3 evicts 2, so the final f(2) is a miss. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
3. library lookup: model, boundary and recovery
Create a small library lookup using a book-code formatter with repeated immutable inputs. Combine “cache_info supplies evidence” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: cache_info returns hits, misses, maxsize and currsize so a learner can evaluate the real call pattern. Apply: Reset, run a representative workload and interpret both hit rate and cost per miss. Verify: The difference should show two misses, one hit and a current size consistent with the distinct retained keys. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
4. science table: model, boundary and recovery
Create a small science table using a conversion calculated from unit and fixed scale. Combine “functools.cache is the unbounded form” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: functools.cache is a simpler unbounded memoizing wrapper, equivalent in purpose to lru_cache with maxsize=None. Apply: Compare key cardinality and lifecycle first; select the spelling that communicates the intended policy. Verify: The recursion reuses completed subproblems without eviction, which is suitable only while the input domain stays controlled. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
5. quiz generator: model, boundary and recovery
Create a small quiz generator using a deterministic question chosen from topic and level. Combine “Purity and hidden dependencies” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: A cached result is sound only while the key captures every dependency that should change the answer. Apply: List all dependencies and either include a version in the key or keep the function uncached. Verify: Changing rate does not invalidate convert(10), so the cache can return a stale result. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
6. budget model: model, boundary and recovery
Create a small budget model using a repeated tax calculation from immutable rates. Combine “Concurrent calls may duplicate work” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: The cache data structure is threadsafe, but another thread can call the underlying function again before the first result is stored. Apply: Use an idempotent function or a stronger single-flight design when duplicate in-flight work is unacceptable. Verify: Two overlapping misses for the same key may both run expensive_lookup even though later calls hit one cached result. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
7. text analysis: model, boundary and recovery
Create a small text analysis using a word feature function called across many sentences. Combine “Invalidation and TTL are separate policies” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: lru_cache provides size-based eviction and manual clearing, not per-entry time-to-live or dependency-aware invalidation. Apply: Define the freshness contract and use versioned keys, scheduled clearing or a cache designed for TTL. Verify: Including a data version makes changed source state produce a new key, while old entries still need lifecycle management. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
8. debug lab: model, boundary and recovery
Create a small debug lab using a counter proving which calls execute and which return cached values. Combine “Arguments must be hashable” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: Every positional and keyword argument used in a cached call must be hashable because it participates in a dictionary-like key. Apply: Convert stable sequence inputs to tuples or redesign the boundary, and test the call before measuring speed. Verify: The tuple is hashable and can form a key; total([2,4,6]) raises TypeError before the body runs. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
Frequently asked questions
How long should a practice session be?
Use one complete prediction–observation–explanation cycle while attention remains good. Ten to twenty focused minutes can be enough.
Should every option or function be memorised?
No. Memorise the governing distinctions and practise retrieving the official reference. Understanding means predicting and explaining, not reciting a parameter list.
What if the result is correct but the explanation is weak?
Treat it as partial success. Ask for a trace and change one boundary. A reliable model survives controlled variation.
Is the shortest solution the best?
Not automatically. Prefer the solution whose semantics, failure modes and maintenance cost are easiest to justify for the actual project.
When should official documentation be used?
Use it whenever syntax, supported types, SQL dialect behaviour or Git version details matter. Primary documentation settles the current contract.
How can a parent help without technical expertise?
Ask what was predicted, where the first difference appeared, what evidence matters and which smaller example could isolate it.
How do we test transfer?
Change the context, vocabulary and one boundary. Require the learner to identify the invariant before using a tool.
What should be saved after practice?
Keep the corrected rule, one trace, one boundary case and the next question. Avoid storing pages of unexplained output.
Can these exercises replace backups?
No. Use disposable examples and proper backups. Learning should not endanger schoolwork, repositories or personal data.
What counts as mastery?
The learner can predict, verify, diagnose, recover and justify a choice across more than one context, while knowing when to consult the current reference.

