A function is a named block of code that does one job. You write it once and call it whenever you need that job done. You have already called many built-in functions, such as print(), len() and sorted(). In this lesson you will write your own Python functions. Functions keep programs short, make them easier to test, and give a clear name to each step of your logic.
Defining and calling Python functions
Start with the keyword def, then the function name, brackets with any parameters, and a colon. The indented block below is the function body. Defining a function does not run it; the body runs only when you call the function by name with brackets.
Most functions send a result back with return. The caller can store that value, print it or pass it to another function. A function without return gives back None. As soon as return runs, the function ends.
def add_gst(amount, rate):
"""Return the amount including GST at the given percentage."""
return amount + amount * rate / 100
laptop = add_gst(50000, 18)
print(laptop)
print(add_gst(250, 5))
def greet(name):
print(f"Vanakkam, {name}!")
result = greet("Selvi")
print(result)59000.0 262.5 Vanakkam, Selvi! None
The text in triple quotes under the def line is a docstring. It documents what the function does, and editors show it when you hover over the function name. Writing one line of docstring for every function is a good habit.
Watch out: Printing is not returning. greet() prints a message but returns None, which is why the last line shows None. If other code needs the result, use return.
Parameters and arguments
Parameters are the names in the def line; arguments are the actual values you pass in a call. Python offers several ways to pass them:
| Feature | Example | Use it when |
|---|---|---|
| Positional arguments | add_gst(500, 18) | There are only one or two obvious values |
| Keyword arguments | add_gst(amount=500, rate=18) | You want the call to explain itself |
| Default values | def add_gst(amount, rate=18): | A parameter usually has the same value |
*args | def total(*prices): | The number of values varies |
**kwargs | def profile(**details): | You want any number of named values |
def ticket_price(base, age, is_student=False):
if age >= 60:
return base // 2
if is_student:
return base - 50
return base
print(ticket_price(300, 35))
print(ticket_price(300, 20, is_student=True))
print(ticket_price(age=65, base=300))
def bill_total(*prices, discount=0):
subtotal = sum(prices)
return subtotal - subtotal * discount / 100
print(bill_total(120, 80, 300))
print(bill_total(120, 80, 300, discount=10))
def profile(name, **details):
print(name, details)
profile("Gowri", city="Erode", role="designer")300
250
150
500.0
450.0
Gowri {'city': 'Erode', 'role': 'designer'}Parameters with defaults must come after those without. Inside the function, *prices arrives as a tuple and **details as a dictionary. Any parameter written after *args, such as discount, can only be passed by keyword, which prevents mix-ups.
Scope: local and global variables
Variables created inside a function are local: they exist only while the function runs and cannot be seen outside it. This is a good thing, because two functions can each use a variable called total without interfering. A function can read a variable defined at the top level of the file, but assigning to that name inside the function creates a new local variable instead. The keyword global changes this, but it makes code harder to follow. It is better to pass values in as arguments and send results out with return.
Returning several values
A function can return several values separated by commas. Python packs them into a tuple, and the caller can unpack them straight into variables, as you learnt in Python Lists and Tuples.
def marks_report(marks: list[int]) -> tuple[int, int, float]:
"""Return the lowest, highest and average mark."""
return min(marks), max(marks), sum(marks) / len(marks)
low, high, avg = marks_report([68, 91, 74, 85])
print(f"Low {low}, high {high}, average {avg:.1f}")
products = [("Saree", 2499), ("Dhoti", 650), ("Kurta", 1199)]
by_price = sorted(products, key=lambda item: item[1])
print(by_price)Low 68, high 91, average 79.5
[('Dhoti', 650), ('Kurta', 1199), ('Saree', 2499)]Type hints
marks: list[int] and -> tuple[int, int, float] are type hints. They describe what the function expects and returns. Python does not enforce them when the code runs, but editors use them to catch mistakes and to offer better suggestions. They are optional, so add them where they make the code clearer.
lambda: tiny anonymous functions
lambda item: item[1] is a one-line function without a name. It takes item and returns item[1]. Lambdas are mainly used as the key for sorted(), min() and max(). If the logic needs more than one simple expression, write a normal def function.
Watch out: Never use a mutable value such as a list as a default: def add_item(item, cart=[]):. The default list is created once and shared between calls, so items pile up unexpectedly. Use cart=None and create a new list inside the function when cart is None.
Tip: Good names for Python functions are verbs that describe the job: calculate_emi(), send_invoice(), is_valid_pincode(). If you struggle to name a function, it may be doing too many jobs; split it into smaller ones.
