Week 2 - Control Flow, Functions, Errors, and the Call Model¶
2.1 Conceptual Core¶
- Functions are first-class objects with attributes (
__name__,__doc__,__annotations__,__defaults__,__closure__,__code__). - Default arguments are evaluated once, at definition time. The single most common Python footgun:
def f(x, acc=[]):-accis shared across calls. UseNonesentinel + body-side default. - EAFP over LBYL.
try: d[k]overif k in d: d[k]. The exception path is fast in CPython when not raised, and the LBYL form races under threads.
2.2 Mechanical Detail¶
- Argument passing: positional, keyword,
*args,**kwargs, positional-only (/, PEP 570), keyword-only (*). Know the order:def f(pos1, pos2, /, both, *, kw_only). - Closures and the
nonlocalkeyword. Late binding in closures ([lambda: i for i in range(3)]returns three lambdas all returning2); fix with default-arg tricklambda i=i: ior with comprehension scoping. - The exception hierarchy:
BaseException→Exception→ everything user-catchable.KeyboardInterruptandSystemExitare siblings ofException, not subclasses -except Exceptiondoes not catch them, by design. - Exception chaining:
raise NewError("...") from cause, implicit chaining via__context__. Exception groups (PEP 654,except*) for concurrent code. try / except / else / finally: theelseruns only if no exception;finallyalways runs, even onreturn.
2.3 Lab - "The Calculator and the Cancel"¶
- Build a tiny expression evaluator over
+ - * /usingast.parse+ a customNodeVisitor. Reject anything else. (Do not useeval.) - Add a
--replmode. MakeCtrl-Cinterrupt the current expression but not exit. MakeCtrl-Dexit cleanly. - Wrap division; raise a custom
EvalErrorchained fromZeroDivisionErrorviafrom. - Add a
--time-budgetflag usingsignal.SIGALRM(POSIX) or a watchdog thread (cross-platform). Document the trade-off.
2.4 Idiomatic & Linter Drill¶
- Enable
ruffrule setTRY(try/except hygiene). Refactor a sample with broadexcept:and bareraiseinto PEP-compliant code.
2.5 Production Hardening Slice¶
- Add
pytestwithpytest-cov. Write tests for the calculator. Aim 100% line and branch coverage for the AST evaluator. Commit a coverage badge target.