What is a for Loop ?

In Python, a for loop is a collection-controlled loop designed to step through a sequence of elements one by one. Unlike traditional programming languages (like C or Java) where a for loop is primarily a modified counter-based index mechanism, Pythonโ€™s for loop functions directly as an iterator.

It eliminates the manual setup of index counters, condition checking, and step increments. Instead, it extracts elements directly from a group of items, running a block of code exactly once for every element present in that collection.

What is an Iterable ?

An Iterable is any Python object capable of returning its member elements one at a time, allowing it to be processed sequentially within a loop. If an object is designed to hold multiple elements and contains the structural framework to hand them over individual by individual, it is classified as an iterable.

Common Python Iterables:

1. Sequences: list, tuple, str (Strings are treated as sequences of individual characters).
2. Non-Sequences: dict (Dictionaries), set.
3. Factory Objects: Objects generated dynamically by the built-in range() function.

Internal Mechanism of Iterables

Technically, an object is recognized as an iterable in Python only if it implements the built-in dunder (double underscore) method __iter__(). When a for loop begins executing, Python invokes this internal __iter__() method behind the scenes to generate an Iteratorโ€”the stateful engine that moves through the collection.

Syntax of for loop

for item in iterable_object:
    # Code block to execute for each item
    statements_to_repeat

1. for : The mandatory keyword that initializes the loop block.
2. item : A temporary placeholder variable identifier chosen by the programmer. During each iteration (turn) of the loop, this variable automatically captures the value of the current element being processed from the sequence.
3. in : A critical Python keyword that binds the temporary placeholder variable to the target data source (the iterable).
4. iterable_object : The source data collection (such as a list, string, or range) containing the group of items you want to traverse.
5. : (Colon) : A syntactical requirement indicating the termination of the loop header and the beginning of the indented code block below it.

Code Example

prices = [100, 200, 300]

for price in prices:
    final_price = price + 18  # Adding 18% tax flat rate
    print(f"Price with Tax: {final_price}")

The for-else Statement

Just like the while loop, Python allows you to attach an optional else block to a for loop. This is another highly specialized feature unique to Python.The core rule governing this structure is: The code inside the else block will execute only if the for loop runs to completion and exhausts the entire iterable naturally. If the loop is terminated prematurely by hitting a break statement, the else block is completely bypassed.

Why do we use it?

It eliminates the old-fashioned programming method of setting up temporary boolean tracking flags (e.g., found = False) when searching for an item within a collection.

Code Example: Verifying Prime Numbers

number_to_check = 13

for i in range(2, number_to_check):
    if number_to_check % i == 0:
        print(f"{number_to_check} is not a prime number (divisible by {i}).")
        break  # Prematurely exits the loop, skipping the else block completely
else:
    # This runs ONLY if the loop checked every number and never hit a 'break'
    print(f"Success! {number_to_check} is a prime number.")

range() Function

In Python, the range() function is a built-in function that generates a predictable sequence of immutable integers on the fly. It is most frequently paired with a for loop when you want to execute a block of code a specific number of times, or when you need a sequence of mathematical index numbers.

The Myth of the "List"

A common misconception among beginners is that range() creates a static list containing all the numbers at once. It does not. Instead, range() returns a lazy-loading range object. It generates each number one by one only when requested by the loop. This makes it incredibly memory efficient, as generating range(1000000) takes up the same minimal system memory as generating range(5).

The Three Syntax Configurations

The range() function is highly flexible and accepts up to three arguments: start, stop, and step.

A: Single Argument range(stop)

When you pass only one number, Python treats it as the execution boundary. 1. start defaults implicitly to 0.
2. step defaults implicitly to 1.
3. It generates numbers up to, but excluding, the stop value.

# Generates numbers: 0, 1, 2, 3, 4
for i in range(5):
    print(i, end=" ")

B: Double Argument range(start, stop)

When you pass two numbers, you can explicitly define where the sequence should begin.
1. start: The exact integer where the sequence starts (inclusive).
2. stop: The integer boundary where the sequence terminates (exclusive).

# Generates numbers from 5 up to (but excluding) 9
for i in range(5, 9):
    print(i, end=" ")

C: Triple Argument range(start, stop, step)

The third argument allows you to customize the numerical increment or decrement gap between each consecutive number.
step: The value added to the current number to compute the next number.

# Generates even numbers starting at 2, adding 2 each time, up to (but excluding) 11
for i in range(2, 11, 2):
    print(i, end=" ")

Counting Backward (Negative Step Value)

The range() function can easily navigate backward down a number line. To count down, your start value must be greater than your stop value, and your step value must be a negative integer.

# Countdown from 5 down to 1 (stops before hitting 0)
for i in range(5, 0, -1):
    print(f"T-minus {i}")
print("Blastoff!")

Rules and Limitations

1. Integer Only Rule : Every argument passed into range() (start, stop, step) must be an integer. Passing float values like range(0.5, 5.5) will immediately trigger a TypeError.
2. Zero Step Error : The step value can never be 0. If you try to run range(1, 10, 0), Python will throw a ValueError: range() arg 3 must not be zero because it would trap the system in an infinite evaluation loop.
3. Empty Sequences : If your structural logic is contradictory, range() will simply return an empty sequence cleanly without throwing an error. For example, range(1, 5, -1) returns nothing because you cannot count backward from 1 to reach 5.

Differences Between For Loop And While Loop

Feature for Loop while Loop
Control Mechanism Collection-Controlled (Runs based on items in a sequence). Condition-Controlled (Runs based on a boolean True/False logic).
Iteration Count Known or fixed in advance based on the size of the iterable. Unknown beforehand; depends entirely on when the condition changes.
Infinite Loop Risk Negligible (Stops naturally when the sequence runs out of items). High (If the update step is missing or condition never becomes False).
State Tracking Updates the item variable and advances the pointer automatically. Requires manual counter initialization and manual update steps.
Best Used For Iterating over lists, tuples, strings, or a fixed range of numbers. Reading files, processing user input, or waiting for specific events.