Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Python Functions

Learn to give code a name: def, parameters and returns, default and keyword arguments, and the scope rules that keep functions honest.

Levels: Beginner ~16 min read

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

python anatomy.py
1
2
3
4
5
6
def price_with_tax(amount, rate):
    """Return the amount after applying tax."""
    return amount * (1 + rate)

total = price_with_tax(45.5, 0.14)
print(total)   # 51.87

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.

python defaults.py
1
2
3
4
5
6
def greet(name, greeting="Hello"):
    return f"{greeting}, {name}!"

greet("Nadia")                 # Hello, Nadia!
greet("Omar", "Good morning")  # Good morning, Omar!
greet("Layla", greeting="Ahlan")  # Ahlan, Layla!

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.

python scope.py
1
2
3
4
5
6
7
8
9
counter = 0          # global

def bump():
    total = 1      # local, vanishes at return
    return total

print(bump())       # 1
print(counter)      # 0, untouched
print(total)        # NameError: it never existed here

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.

Interactive Runnable example
Edit

Ready to run.

What to notice

  • Changing behavior meant changing one function, and every call site followed.

  • The keyword call rate=0.05 overrode 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.

Was this page helpful?

Mark this learning resource complete to track your learning progress.