intermediate Step 9 of 20

Functions

Python Programming

Functions

Functions are reusable blocks of code that perform a specific task. They are one of the most important concepts in programming because they allow you to organize code into logical units, avoid repetition (DRY — Don't Repeat Yourself), and make your programs easier to read, test, and maintain. In Python, functions are first-class objects, meaning they can be assigned to variables, passed as arguments to other functions, and returned from functions.

Defining and Calling Functions

# Basic function definition
def greet():
    print("Hello, World!")

greet()  # Call the function

# Function with parameters
def greet_person(name):
    print(f"Hello, {name}!")

greet_person("Alice")  # "Hello, Alice!"

# Function with return value
def add(a, b):
    return a + b

result = add(3, 5)
print(result)  # 8

# Returning multiple values (as a tuple)
def get_stats(numbers):
    return min(numbers), max(numbers), sum(numbers) / len(numbers)

lo, hi, avg = get_stats([4, 8, 15, 16, 23, 42])
print(f"Min: {lo}, Max: {hi}, Avg: {avg:.1f}")

Parameters and Arguments

# Default parameters
def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Alice")             # "Hello, Alice!"
greet("Bob", "Hi")         # "Hi, Bob!"

# Keyword arguments
def create_user(name, age, role="user"):
    return {"name": name, "age": age, "role": role}

user = create_user(name="Alice", age=30, role="admin")
user2 = create_user("Bob", age=25)  # Positional + keyword

# *args — variable positional arguments
def calculate_sum(*numbers):
    total = 0
    for num in numbers:
        total += num
    return total

print(calculate_sum(1, 2, 3))          # 6
print(calculate_sum(10, 20, 30, 40))   # 100

# **kwargs — variable keyword arguments
def build_profile(name, **details):
    profile = {"name": name}
    profile.update(details)
    return profile

profile = build_profile("Alice", age=30, city="NYC", job="Developer")
print(profile)
# {'name': 'Alice', 'age': 30, 'city': 'NYC', 'job': 'Developer'}

# Combining all parameter types
def complex_func(a, b, *args, option=True, **kwargs):
    print(f"a={a}, b={b}")
    print(f"args={args}")
    print(f"option={option}")
    print(f"kwargs={kwargs}")

complex_func(1, 2, 3, 4, option=False, x=10, y=20)

Scope and Variable Visibility

# Local vs global scope
x = "global"

def my_func():
    x = "local"      # This is a different variable
    print(x)          # "local"

my_func()
print(x)              # "global" (unchanged)

# Using global keyword (generally avoid this)
counter = 0

def increment():
    global counter
    counter += 1

increment()
print(counter)  # 1

# Enclosing scope (closures)
def outer():
    message = "Hello"
    def inner():
        print(message)  # Accesses enclosing scope
    inner()

outer()  # "Hello"

# nonlocal keyword
def counter_factory():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

counter = counter_factory()
print(counter())  # 1
print(counter())  # 2
print(counter())  # 3

Lambda Functions

# Lambda — anonymous one-line functions
square = lambda x: x ** 2
print(square(5))  # 25

add = lambda a, b: a + b
print(add(3, 4))  # 7

# Commonly used with sorted(), map(), filter()
students = [("Alice", 90), ("Bob", 78), ("Charlie", 95)]
sorted_by_score = sorted(students, key=lambda s: s[1], reverse=True)
print(sorted_by_score)  # [('Charlie', 95), ('Alice', 90), ('Bob', 78)]

# map and filter
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
squared = list(map(lambda x: x**2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(squared)  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print(evens)    # [2, 4, 6, 8, 10]

Type Hints and Docstrings

def calculate_bmi(weight_kg: float, height_m: float) -> float:
    """Calculate Body Mass Index (BMI).

    Args:
        weight_kg: Weight in kilograms.
        height_m: Height in meters.

    Returns:
        The BMI value as a float.

    Raises:
        ValueError: If height is zero or negative.
    """
    if height_m <= 0:
        raise ValueError("Height must be positive")
    return weight_kg / (height_m ** 2)

bmi = calculate_bmi(70, 1.75)
print(f"BMI: {bmi:.1f}")  # BMI: 22.9
Pro tip: Follow the single-responsibility principle: each function should do one thing and do it well. If a function is getting too long (more than 20-30 lines) or doing multiple unrelated things, break it into smaller functions.

Key Takeaways

  • Functions are defined with def, can accept parameters, and return values with return.
  • Python supports default parameters, keyword arguments, *args (variable positional), and **kwargs (variable keyword).
  • Variables inside functions have local scope; use global and nonlocal sparingly to modify outer variables.
  • Lambda functions provide concise anonymous functions for simple operations, commonly used with sorted(), map(), and filter().
  • Always write docstrings and consider type hints for better code documentation and IDE support.