Lesson 4 of 34 · 0 of 3 exercises solved

Functions

are named, reusable blocks of code. They let you write logic once, call it from many places, and change it in one spot.

Define functions with the keyword. can have default values, and Python supports both positional and when calling functions.

# Basic function
def greet(name):
    return f"Hello, {name}!"

print(greet("Alice"))   # Hello, Alice!

# Default parameter values
def greet_with_title(name, title="Dr."):
    return f"Hello, {title} {name}!"

print(greet_with_title("Smith"))           # Hello, Dr. Smith!
print(greet_with_title("Jones", "Prof."))  # Hello, Prof. Jones!

# Multiple return values (returns a tuple)
def min_max(numbers):
    return min(numbers), max(numbers)

lo, hi = min_max([3, 1, 4, 1, 5, 9, 2, 6])
print(lo, hi)   # 1 9

# *args — variable number of arguments
def total(*args):
    return sum(args)

print(total(1, 2, 3, 4))   # 10

# **kwargs — keyword arguments as a dict
def describe(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

describe(name="Alice", age=30, city="Paris")
Python (loads on first run)Ctrl+Enter runs

functions are anonymous single-expression functions, useful for short operations passed to higher-order functions like sorted(), map(), and filter().

# Lambda: lambda parameters: expression
square = lambda x: x ** 2
print(square(5))   # 25

# Common use: sorting with a custom key
people = [("Alice", 30), ("Bob", 25), ("Charlie", 35)]
sorted_by_age = sorted(people, key=lambda p: p[1])
print(sorted_by_age)   # [('Bob', 25), ('Alice', 30), ('Charlie', 35)]

# map() — apply function to every element
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
print(squares)   # [1, 4, 9, 16, 25]

# filter() — keep elements where function returns True
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)   # [2, 4]
Python (loads on first run)Ctrl+Enter runs

Common question

Is a function worth writing if I only call it once?

A function is a named piece of work with defined inputs and a returned output. Its value is as much in the name as in reuse: it lets you think about a program in bigger chunks, test each chunk alone, and change how something works without touching the code that calls it. That is why experienced programmers pull out functions freely, including ones called from a single place.

The mechanics to remember are few. Parameters point at the caller's objects, so mutating them affects the caller and rebinding them does not. Default values are created once, when the function is defined. A function with no return gives back . Positional arguments come first, then keyword arguments, and *args and **kwargs collect any extras.

Source: Edsger Dijkstra: "The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise."

Common mix-ups

Each of these sounds reasonable. Think about why it is wrong, then open the explanation.

  • Functions exist for reuse, so code used once should stay inline.

  • Function parameters are copies, so changing a inside a function is safe.

  • A default value like items=[] is created fresh on every call.

Practice

Write is_palindrome(text) that returns True when the text reads the same forwards and backwards, ignoring case and spaces. "Never odd or even" should count.

Exercise

Palindrome checker

3 checks
def is_palindrome(text):
    # normalise, then compare with the reversed string
    ...


print(is_palindrome("racecar"))
print(is_palindrome("Never odd or even"))
print(is_palindrome("python"))
 
Python (loads on first run)Ctrl+Enter runs
Output
Press Run to try your code, then Check answer to grade it.

Write average(*numbers) that accepts any number of arguments and returns their mean. With no arguments it should return 0 rather than crashing.

Exercise

Variadic average

4 checks
def average(*numbers):
    ...


print(average(2, 4, 6))
print(average())
 
Python (loads on first run)Ctrl+Enter runs
Output
Press Run to try your code, then Check answer to grade it.

Write greet(name, greeting="Hello") that returns a like Hello, Ada! — and make it possible to change the greeting with a keyword argument.

Exercise

Default and keyword arguments

3 checks
def greet(name):
    return "Hello, " + name


print(greet("Ada"))
print(greet("Grace", greeting="Good morning"))
 
Python (loads on first run)Ctrl+Enter runs
Output
Press Run to try your code, then Check answer to grade it.

Check yourself

Quick check

What does this function return when called as add_item("apple") twice in a row?

Python
def add_item(item, basket=[]):
    basket.append(item)
    return basket
Finished reading?3 exercises still open. You can come back to them later.

Tip: use the ← and → keys to move between lessons.