Functions — def, Return Values & Default Arguments
BeginnerFunctions are first-class objects defined with def, returning None unless told otherwise — with keyword arguments and default values that make call sites self-documenting.
Overview
Python functions are objects: you can assign them to variables, pass them around, and store them in dicts (that's how routing tables and strategy patterns work without interfaces). Every function returns something — None if you don't return explicitly. Arguments can be passed by position or by name (keyword arguments), and defaults make parameters optional. One famous trap lives here: mutable default arguments are evaluated ONCE at definition time — the single most-asked Python interview gotcha.
Definition, Keyword Args & Multiple Returns
Call with names for readability (send_mail(to="x", urgent=True)). Returning multiple values actually returns one tuple, unpacked at the call site.
def apply_discount(price, percent=10): # percent is optional
discounted = price * (1 - percent / 100)
return round(discounted, 2)
apply_discount(1000) # 900.0 — default used
apply_discount(1000, 25) # 750.0 — positional
apply_discount(price=1000, percent=25) # named — self-documenting
# "Multiple" return values = one tuple
def min_max(nums):
return min(nums), max(nums) # returns a tuple
lo, hi = min_max([4, 9, 1]) # unpacked
print(lo, hi) # 1 9
# Functions are objects
operations = {"double": lambda x: x * 2, "square": lambda x: x ** 2}
print(operations["square"](6)) # 36THE Trap: Mutable Default Arguments
Default values are evaluated once, when def runs — not on every call. A mutable default (list/dict) is therefore SHARED across all calls. The fix: default to None and create inside.
# BUG — the default list is created ONCE
def add_task(task, tasks=[]):
tasks.append(task)
return tasks
print(add_task("read")) # ['read']
print(add_task("code")) # ['read', 'code'] ← surprise! same list
# FIX — None sentinel
def add_task(task, tasks=None):
if tasks is None:
tasks = [] # fresh list per call
tasks.append(task)
return tasks
print(add_task("read")) # ['read']
print(add_task("code")) # ['code'] ✓Key Points to Remember
- 1No explicit return → the function returns None
- 2Keyword arguments make call sites readable; defaults make params optional
- 3NEVER use mutable defaults (list/dict) — use None + create inside
- 4Returning a, b returns a tuple; unpack with x, y = f()
Interview Questions
Sign in to ask AriaWhat is wrong with def f(x, items=[])? Explain exactly why and fix it.
What does a Python function return if there is no return statement?
How does Python return multiple values from a function — what is really happening?
Ask Aria about Functions — def, Return Values & Default Arguments
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.