English
Summary
Conclusions
A function combines a name, parameters, a contract, and a result. Its signature determines how an argument is passed; modifying a shared object differs from reassigning a local name. A closure retains state in an enclosing function. Recursion is suitable when a problem naturally splits into smaller ones, but requires a base case, limits, and control of repeated calculations. Annotations make these agreements visible to readers and tools.
Self-check questions
- How does a parameter differ from an argument?
- When does a
defbody run, and when are default values evaluated? - How do
return,print, and implicitNonediffer? - What does
return low, highactually return? - How do the
/and*markers work? - How does collecting arguments differ from unpacking?
- Why does a default list retain changes between calls?
- Why does reassigning a parameter not replace the caller's list?
- What is the LEGB name lookup order?
- When are
globalandnonlocalneeded? - What data does a closure retain?
- What proves that recursion terminates?
- Why does Fibonacci caching not eliminate stack depth?
- How do you annotate a function argument?
- How do deferred annotations differ from string annotations?
Useful links
- Functions and parameters: https://docs.python.org/3.14/tutorial/controlflow.html.
- Scope: https://docs.python.org/3.14/reference/executionmodel.html.
- Typing: https://docs.python.org/3.14/library/typing.html.
- Deferred annotations: https://docs.python.org/3.14/library/annotationlib.html.