Define reusable functions with parameters, default values and return values.
Why it matters
As programs grow, you find yourself writing the same few lines in several places: converting units, validating a value, formatting a report line. A function gives those lines a name so you can write them once and use them everywhere. Functions also make code easier to test, because you can check one small piece at a time, and easier to read, because a good name like celsius_to_fahrenheit explains itself.
Defining and calling a function
def celsius_to_fahrenheit(celsius):
fahrenheit = celsius * 9 / 5 + 32
return fahrenheit
print(celsius_to_fahrenheit(100)) # 212.0
print(celsius_to_fahrenheit(-40)) # -40.0
The parts:
defstarts the definition, followed by the function's name.- Inside the parentheses are the parameters: names for the inputs. Here,
celsius. - The colon and the indented block form the body.
returnsends a value back to whoever called the function, and ends the function immediately.
Defining a function does not run it. It runs only when you call it, writing its name with arguments in parentheses: celsius_to_fahrenheit(100). The value 100 is assigned to the parameter celsius for that call.
return versus print
This difference trips up almost every beginner:
def area_print(width, height):
print(width * height)
def area_return(width, height):
return width * height
a = area_print(3, 4) # shows 12, but a is None
b = area_return(3, 4) # shows nothing, but b is 12
print(b * 2) # 24
print shows a value on the screen and then the value is gone. return hands the value back so the rest of your program can use it. A function with no return statement returns the special value None. As a rule, functions that calculate something should return it and let the caller decide whether to print it.
Several parameters and default values
def bmi(mass_kg, height_m):
return mass_kg / height_m ** 2
print(round(bmi(70, 1.75), 1)) # 22.9
Arguments are matched to parameters by position. You can also pass them by name, which is clearer when there are several:
print(round(bmi(height_m=1.75, mass_kg=70), 1)) # 22.9
A parameter can have a default value, used when the caller leaves it out:
def format_temp(value, unit="C", decimals=1):
return f"{value:.{decimals}f} °{unit}"
print(format_temp(21.456)) # 21.5 °C
print(format_temp(70.8, "F")) # 70.8 °F
print(format_temp(21.456, decimals=2)) # 21.46 °C
Parameters with defaults must come after the ones without.
Returning early and returning several values
return can appear more than once. The first one reached wins:
def safe_divide(a, b):
if b == 0:
return None # nothing sensible to return
return a / b
To return several values, separate them with commas. Python packs them into a tuple, and the caller can unpack them:
def min_max(values):
return min(values), max(values)
low, high = min_max([7, 2, 9, 4])
print(low, high) # 2 9
Scope: variables inside functions
Variables created inside a function are local: they exist only while the function runs and cannot be seen from outside.
def add_tax(price):
tax = price * 0.2
return price + tax
print(add_tax(10)) # 12.0
print(tax) # NameError: name 'tax' is not defined
This is a feature. It means a function cannot accidentally overwrite your other variables, and you can understand it on its own. Pass what a function needs in as arguments, and get results out with return, rather than relying on variables defined elsewhere.
Documenting a function
A string on the first line of the body is a docstring. It describes what the function does, and tools such as help() and code editors show it:
def average(values):
"""Return the mean of a list of numbers, or 0.0 for an empty list."""
if not values:
return 0.0
return sum(values) / len(values)
A worked example: building from small pieces
Small functions combine into bigger ones:
def average(values):
if not values:
return 0.0
return sum(values) / len(values)
def report(name, values):
return f"{name}: mean {average(values):.1f} from {len(values)} readings"
print(report("Tank A", [20.5, 21.0, 22.5]))
# Tank A: mean 21.3 from 3 readings
Each function does one job and can be tested on its own. That is the habit that makes larger programs manageable.
Common mistakes
- Forgetting the parentheses.
celsius_to_fahrenheitwithout()refers to the function itself; it does not call it. - Printing instead of returning. If the caller needs the value,
returnit. - Code after
return. Lines after areturnin the same block never run. - Calling before defining. Python runs top to bottom, so define a function above the line that first calls it.
- Mutable default values.
def add(item, items=[])shares one list across every call. Useitems=None, thenif items is None: items = [].
Quick recap
def name(parameters):defines a function; callingname(arguments)runs it.returnsends a value back; without it, a function returnsNone.- Default values make parameters optional; keyword arguments make calls readable.
- Variables inside a function are local to it.
- Small, single-purpose functions are easier to test and reuse.
Try it
In the Do tab you will write a unit converter, a safe average and a formatter that uses a default value.