Intermediate
Functions
Learn to define reusable functions, handle parameters flexibly, use lambda expressions, understand scope, and get started with decorators.
Defining Functions
Functions are reusable blocks of code defined with the def keyword:
Python
def greet(name): """Greet a person by name.""" print(f"Hello, {name}!") greet("Alice") # Hello, Alice! greet("Bob") # Hello, Bob!
Parameters and Arguments
Python
# Positional arguments def add(a, b): return a + b print(add(3, 5)) # 8 # Keyword arguments def describe(name, age, city): print(f"{name} is {age} from {city}") describe(age=30, city="NYC", name="Alice")
Return Values
Python
def calculate(a, b): """Return multiple values as a tuple.""" total = a + b diff = a - b product = a * b return total, diff, product s, d, p = calculate(10, 3) print(s, d, p) # 13 7 30
Default Parameters
Python
def power(base, exponent=2): return base ** exponent print(power(5)) # 25 (uses default exponent=2) print(power(5, 3)) # 125
Never use mutable default arguments! Using
def func(items=[]) is a common bug — the list is shared across all calls. Use def func(items=None) and set items = items or [] inside the function.*args and **kwargs
Python
# *args - variable positional arguments (tuple) def sum_all(*args): return sum(args) print(sum_all(1, 2, 3, 4)) # 10 # **kwargs - variable keyword arguments (dict) def build_profile(**kwargs): return kwargs profile = build_profile(name="Alice", age=30, role="Engineer") print(profile) # {'name': 'Alice', 'age': 30, 'role': 'Engineer'} # Combining all parameter types def example(required, *args, default=10, **kwargs): print(required, args, default, kwargs)
Lambda Functions
Anonymous, single-expression functions:
Python
# Lambda syntax square = lambda x: x ** 2 print(square(5)) # 25 # Common use: sorting with custom key students = [("Alice", 90), ("Bob", 85), ("Charlie", 92)] students.sort(key=lambda s: s[1], reverse=True) # [('Charlie', 92), ('Alice', 90), ('Bob', 85)]
Scope: Local vs Global
Python
x = 10 # Global variable def outer(): y = 20 # Local to outer def inner(): z = 30 # Local to inner print(x, y, z) # Can access all three inner() outer() # 10 20 30 # Modify global inside function def increment(): global x x += 1 increment() print(x) # 11
Docstrings
Python
def calculate_bmi(weight_kg, height_m): """ Calculate Body Mass Index (BMI). Args: weight_kg (float): Weight in kilograms. height_m (float): Height in meters. Returns: float: The BMI value. Example: >>> calculate_bmi(70, 1.75) 22.86 """ return round(weight_kg / height_m ** 2, 2)
Built-in Functions
Python
nums = [1, 2, 3, 4, 5] # map - apply function to each element doubled = list(map(lambda x: x * 2, nums)) # [2, 4, 6, 8, 10] # filter - keep elements that match condition evens = list(filter(lambda x: x % 2 == 0, nums)) # [2, 4] # zip - pair elements from multiple iterables names = ["Alice", "Bob"] scores = [95, 87] for name, score in zip(names, scores): print(f"{name}: {score}") # enumerate - loop with index for i, val in enumerate(nums, start=1): print(f"{i}. {val}")
Decorators (Introduction)
Decorators wrap a function to extend its behavior without modifying it:
Python
import time def timer(func): """Decorator that measures execution time.""" def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) elapsed = time.time() - start print(f"{func.__name__} took {elapsed:.4f}s") return result return wrapper @timer def slow_function(): time.sleep(1) return "Done!" slow_function() # slow_function took 1.0012s
Functions are first-class objects in Python. You can assign them to variables, pass them as arguments, and return them from other functions. This is what makes decorators and higher-order functions possible.
Lilly Tech Systems