Python Functions
Learn to give code a name: def, parameters and returns, default and keyword arguments, and the scope rules that keep functions honest.
Basic
A function is a named, reusable piece of behavior. You define it once with
def and call it by name whenever the behavior is needed, with different inputs each time. That is the whole mechanism, and it is the difference between a script that is read once and a program that is maintained for years. Good functions earn their names the way good variables do: a reader meets the name and knows what the code will do before reading it.
def, parameters, return
|
|
Name, parameters, docstring, return: the complete anatomy.
The parameters are the inputs the function promises to accept, and the
return statement is the output it promises to hand back. Execution inside a function stops at the first
return it meets, and a function that runs off the end without one returns
None, quietly, which is why a missing return shows up as
None in output rather than as an error message.
Arguments: positional, keyword, default
Calls fill parameters in order, so
price_with_tax(45.5, 0.14) binds
amount then
rate. Any argument may instead be passed by name,
price_with_tax(amount=45.5, rate=0.14), which costs a few characters and buys calls that read themselves, worth it at every call site where bare numbers would be mysterious. Parameters can also declare defaults, which make arguments optional.
|
|
Defaults make arguments optional; names make calls legible.
Scope: what a function can see
Names created inside a function are local: they exist while it runs and vanish when it returns. Names created at the top level of a module are global, visible to functions for reading but not, without a deliberate
global declaration, for assignment. This one-way visibility is not a limitation to work around; it is what makes a function understandable on its own terms, needing only its parameters and a promise to return.
|
|
Locals stay local; globals are read, not seized.
Composition: functions calling functions
The real payoff arrives when small functions call each other. A receipt is a formatting function applied to a pricing function applied to a counting function, and each level stays short enough to check by reading. Programs built this way grow in the shape of their problem, with names doing the work that comments and cleverness do in weaker codebases.
Run a small receipt engine
The example below is the bakery's morning arithmetic, composed from three functions. Run it, then exercise the design: change the tax rate in one place and watch both receipts change, the whole point of the name being defined once. Add a
discount parameter with a default of zero to
line_total and pass it by keyword from one call only. And try deleting the
return from
line_total to meet the silent
None that shows up in the receipt instead of a price.
Output
Ready to run.
What to notice
Changing behavior meant changing one function, and every call site followed.
The keyword call
rate=0.05overrode a default for one line without touching the others.Composition read top-down as a sentence: a receipt line is tax applied to a line total.
Quick check
If you can explain why a missing return prints
None instead of raising, why mutable defaults are a trap, and what a function can read but not assign, you have the machinery every larger program is built from. That completes the Python path: variables, numbers, strings, decisions, containers, loops, and now names for all of it. Revisit any lesson through the Python learning page, and test yourself along the way — starting with the Python Functions quiz.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.