← Back to Python series
🌱
Basic
def · return · Arguments · Defaults · Scope

Week 9 — Functions

Functions let you name and reuse blocks of logic. Learn def, return, default arguments, keyword arguments, and variable scope (LEGB rule).

functiondefreturnscopearguments
Duration
2.5 hours
Level
📊 Beginner
Prerequisite
🎯 Week 5
OUTCOME
Refactor a calculator into well-named functions with docstrings

What you'll learn

  • 1Define and call functions with def
  • 2Return single and multiple values
  • 3Use positional, keyword, and default arguments
  • 4Understand the LEGB scope rule
  • 5Write docstrings to document functions

1. Defining Functions

python
def greet(name):
    """Return a greeting string."""
    return f"Hello, {name}!"

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

Always write a docstring (triple-quoted string right after def) to document what the function does.

2. Return Values

python
def divide(a, b):
    if b == 0:
        return None, "Division by zero"
    return a / b, None

result, error = divide(10, 2)
if error:
    print(error)
else:
    print(result)  # 5.0

3. Arguments

python
def power(base, exp=2):          # default argument
    return base ** exp

print(power(3))       # 9  (exp defaults to 2)
print(power(3, 3))    # 27
print(power(exp=3, base=2))  # keyword arg: 8

4. Scope (LEGB)

Python looks up variable names in this order: Local → Enclosing → Global → Built-in.

python
x = 10          # global

def func():
    x = 20      # local — does NOT change the global x
    print(x)    # 20

func()
print(x)        # 10

# To modify global x inside a function:
def func2():
    global x
    x = 99
func2()
print(x)        # 99

5. Common Mistakes

  1. A function without return returns None implicitly.
  2. Mutable default arguments (def f(lst=[])) are shared between calls — use def f(lst=None): lst = lst or [].
  3. Calling a function before defining it → NameError. Define first, call second.

💻 Examples

Run these examples and check the output yourself.

01_calculator_funcs.pyCalculator refactored into functions
CODE
def add(a, b): return a + b
def sub(a, b): return a - b
def mul(a, b): return a * b
def div(a, b): return a / b if b else "Error: division by zero"

a = float(input("a: "))
b = float(input("b: "))
print(f"  +: {add(a,b)}")
print(f"  -: {sub(a,b)}")
print(f"  *: {mul(a,b)}")
print(f"  /: {div(a,b)}")
02_stats.pyStatistical functions
CODE
def mean(lst):
    return sum(lst) / len(lst)

def variance(lst):
    m = mean(lst)
    return sum((x - m)**2 for x in lst) / len(lst)

def std_dev(lst):
    return variance(lst) ** 0.5

data = [10, 20, 30, 40, 50]
print(f"Mean:    {mean(data):.2f}")
print(f"Std Dev: {std_dev(data):.2f}")
▶ Output
Mean:    30.00
Std Dev: 14.14
03_recursive_factorial.pyFactorial using recursion
CODE
def factorial(n):
    """Return n! recursively."""
    if n <= 1:
        return 1
    return n * factorial(n - 1)

for i in range(1, 8):
    print(f"{i}! = {factorial(i)}")
▶ Output
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040

📝 Exercises

Try them yourself first, then open the solution to compare.

Exercise 1

Is Prime?

Goal: Write is_prime(n) that returns True if n is prime.

Requirements
  • Handle n < 2 → False
  • Check divisors only up to sqrt(n)
  • Test for n = 1, 2, 17, 100
Toggle solution
SOLUTION
def is_prime(n):
    if n < 2: return False
    for i in range(2, int(n**0.5)+1):
        if n % i == 0: return False
    return True

for n in [1, 2, 17, 100]:
    print(f'is_prime({n}) = {is_prime(n)}')
▶ Output
is_prime(1) = False
is_prime(2) = True
is_prime(17) = True
is_prime(100) = False
Exercise 2

Caesar Cipher

Goal: Write encrypt(text, shift) that shifts each letter by shift positions.

Requirements
  • Preserve case (upper/lower)
  • Non-alpha characters pass through unchanged
  • Write a matching decrypt(text, shift)
Sample I/O
encrypt('Hello, World!', 3) → 'Khoor, Zruog!'
Toggle solution
SOLUTION
def encrypt(text, shift):
    result = []
    for c in text:
        if c.isalpha():
            base = ord('A') if c.isupper() else ord('a')
            result.append(chr((ord(c) - base + shift) % 26 + base))
        else:
            result.append(c)
    return ''.join(result)

def decrypt(text, shift):
    return encrypt(text, -shift)

print(encrypt('Hello, World!', 3))
print(decrypt('Khoor, Zruog!', 3))
▶ Output
Khoor, Zruog!
Hello, World!
Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub ↗