🚀 2.3 Functions, Loops, and Control Flow in Python

This notebook introduces three fundamental programming concepts in Python that will help you write efficient, readable, and reusable code for data analysis in nutrition and food science:


🧠 Why These Concepts Matter

Without these tools, you’d have to write the same code over and over. Instead, you can: - Use functions to wrap a task and reuse it whenever needed. - Use loops to apply actions across a dataset. - Use if/else to act differently depending on the situation.

For example, you might want to: - Convert calories to kilojoules for all hippos in a dataset. - Calculate the percentage of nutrient reference intake. - Flag hippos with low calcium intake.


🧪 What Is a Function in Python?

A function in Python is a named block of reusable code that performs a specific task. Think of it like a mini-program within your programme. Functions help you organise, reuse, and simplify your code—especially useful when analysing large nutrition datasets or performing repetitive tasks (like unit conversions or calculations for every participant).

🧭 Why Use Functions?

  • Avoid repetition: Write code once, use it many times.
  • Make code clearer: Logical blocks are easier to understand.
  • Support teamwork: Functions allow modularity—team members can focus on specific tasks.
  • Enable testing and debugging: You can test individual functions to ensure they behave as expected.

🧰 Defining a Function

def greet():
    """This function prints a greeting."""
    print("Hello, hippo!")

To use it, you call the function by name with ():

greet()

📦 Functions with Inputs (Arguments)

You can pass inputs into functions—these are called arguments. For example, to create a function that greets a specific hippo by ID:

def greet_hippo(hippo_id):
    """Greets a hippo by ID."""
    print(f"Hello, Hippo {hippo_id}!")

Then call it like this:

greet_hippo("H3")

🎯 Functions That Return Values

Some functions do a calculation and return a result using the return keyword:

def nutrient_percentage(intake, reference):
    """Returns intake as a percentage of reference."""
    return round((intake / reference) * 100, 1)

Calling this function:

result = nutrient_percentage(8.2, 15)
print(result)  # 54.7

📘 What Is a Docstring?

A docstring is a special comment enclosed in triple quotes """ that explains what the function does, its inputs, and output. These appear when using help() and are best practice in well-written code:

def calculate_bmi(weight, height):
    """
    Calculates Body Mass Index (BMI).
    
    Args:
        weight (float): Weight in kilograms.
        height (float): Height in meters.
        
    Returns:
        float: BMI value
    """
    return weight / (height ** 2)

🔒 Scope: Where Variables Exist

Variables defined inside a function only exist while that function runs. This is called local scope.

def local_example():
    x = 42  # This exists only inside the function
    print(x)

local_example()
# print(x)  # ❌ This would give an error

🔁 Introduction to Loops in Python

Loops are fundamental programming structures that allow you to repeat actions without writing the same code multiple times. In Python, loops are especially useful when dealing with lists, datasets, or repeated calculations, such as iterating over nutrient intake records.


🔄 What Is a Loop?

A loop is a block of code that runs repeatedly based on a condition. Python primarily supports two types of loops:

  • for loops: Used to iterate over a sequence (like a list or string)
  • while loops: Repeats as long as a condition is True

🧪 Example: for Loop

hippos = ['H1', 'H2', 'H3']
for hippo in hippos:
    print(f"Analysing data for hippo {hippo}")

Explanation:

  • hippos is a list of values
  • The for loop processes each item one by one
  • The variable hippo takes on each value in the list, and the code inside the loop runs for each

⏳ Example: while Loop

energy = 100
while energy > 0:
    print(f"Energy remaining: {energy}")
    energy -= 20  # decrease energy

Explanation:

  • The loop runs as long as energy > 0 is True
  • Each time it runs, it prints the energy level and reduces it by 20
  • Once energy reaches 0, the loop stops

🛠️ Loop Tools: range(), enumerate(), zip()

range(start, stop, step)

Generates a sequence of numbers.

for i in range(1, 6):
    print(f"Day {i}")

enumerate()

Gives you both index and value during iteration.

foods = ['carrots', 'apples', 'hay']
for index, item in enumerate(foods):
    print(f"{index}: {item}")

zip()

Combines two or more sequences into tuples.

hippos = ['H1', 'H2']
weights = [1500, 1600]
for hippo, weight in zip(hippos, weights):
    print(f"Hippo {hippo} weighs {weight} kg")

🔀 Introduction to Conditionals in Python

In Python, conditionals are used to control the flow of your programme. They allow your code to make decisions—just like a hippo might decide whether to eat the carrot or the watermelon depending on the weather!

🧠 What Are Conditionals?

Conditionals check whether something is True or False. Based on the result, Python will execute a specific block of code. This allows your programme to behave differently under different circumstances.


✅ Basic Structure

The most common keywords in conditional logic are:

  • if: checks a condition
  • elif: checks another condition if the previous one was False
  • else: runs if all previous conditions were False

📦 Example

iron_intake = 6.5  # in mg

if iron_intake < 8:
    print("Iron intake is below recommended.")
elif iron_intake == 8:
    print("Iron intake is exactly on target.")
else:
    print("Iron intake exceeds recommendation.")

⚠️ Indentation Matters

Just like loops and functions, conditionals rely on indentation to define blocks of code. Each clause (if/elif/else) ends in a colon : and the block underneath must be indented.

calories = 2200

if calories > 2500:
    print("High energy intake")
else:
    print("Within normal range")

🧪 Nested Conditionals

You can also put one conditional inside another, though it’s good practice to keep things readable.

protein = 60  # in grams

if protein > 50:
    if protein < 75:
        print("Moderate protein intake")
    else:
        print("High protein intake")

🐍 Pythonic Alternatives

Sometimes, short decisions can be made with a ternary expression:

iron_intake = 6.5
status = "Low" if iron_intake < 8 else "OK"
print(status)

✅ Conclusion: Tying It All Together

Congratulations! You’ve now met three of Python’s most important programming tools:

  • Functions: reusable blocks of code that make your scripts cleaner and more modular
  • Loops: ways to repeat actions efficiently without copy-pasting code
  • Conditionals: decision-making logic that helps your programme respond to different situations

These are the core building blocks of any real-world data analysis. Whether you’re calculating daily intakes for a herd of hippos 🦛, validating spreadsheet entries, or flagging unusual results, you’ll use these tools again and again.

Good programming, like good nutrition, is about balance, structure, and clarity.


🌟 Advanced Insights (Click to expand)

🧠 Lambda Functions (Anonymous Functions)

Sometimes you just need a simple one-line function for quick tasks. Enter the lambda function:

double = lambda x: x * 2
print(double(4))  # ➝ 8

Very handy inside functions like map() or filter().


🌀 List Comprehensions

Loops can often be replaced with elegant one-liners:

calories = [2500, 2600, 2300]
kilojoules = [c * 4.184 for c in calories]
kilojoules

🔁 while Loops

Besides for, you also have while loops, which run as long as a condition is true:

x = 0
while x < 5:
    print(x)
    x += 1

⚠️ Nested Logic and Complexity

Watch out for overly complex nesting! If you have functions inside loops inside conditionals inside other functions… it’s probably time to break it up.


👉 Up next: you’ll dive into Python’s data structures—lists, tuples, dictionaries, and sets—essential for organising and managing your nutrition data like a pro.