Skip to main content
Fundamentals•Last Updated : 02 Oct 2026
~30 min read

For Loops, Range Generators & Iterator Protocols

Deep dive into deterministic counting loops, generator ranges, iterator protocols (__iter__ / __next__), index vs value iteration, and nested iteration complexity.

1. The Iterator Protocol & Memory Efficiency

A for loop in modern computer science is fundamentally an abstraction over an Iterator Protocol. Rather than loading an entire sequence into memory simultaneously, an iterator yields one element at a time on demand via constant O(1) space pointer increments.

Range Generators vs Full Sequence Materialization:

In Python 3, range(1, 10_000_000) consumes only 48 bytes of memory because it calculates values algorithmically using start, stop, and step arithmetic without allocating an array of 10 million integers in heap RAM.

1matrix = [
2 [1, 2, 3],
3 [4, 5, 6],
4 [7, 8, 9]
5]
6
7# Flatten matrix and compute row sums using for loops
8row_sums = []
9for r_idx, row in enumerate(matrix):
10 current_sum = 0
11 for val in row:
12 current_sum += val
13 row_sums.append(current_sum)
14 print(f'Row {r_idx} Sum: {current_sum}')
15
16print('Total Processed Rows:', len(row_sums))
Output
Row 0 Sum: 6
Row 1 Sum: 15
Row 2 Sum: 24
Total Processed Rows: 3

2. Nested Loops & Asymptotic Big-O Analysis

When loops are nested, the total operations executed equals the product or summation of their iteration spaces.

  • Square Grid: Outer loop runs N times; inner loop runs M times -> Total Time Complexity = O(N * M).
  • Triangular / Combinatorial: Outer loop runs i from 0 to N-1; inner loop runs j from i + 1 to N-1. The number of steps is (N * (N - 1)) / 2, which simplifies asymptotically to O(N^2).

Loop Pattern Complexity Benchmarks

StructureInner OperationsTotal OperationsBig-O Time
Single Linear ScanO(1) constantN stepsO(N) Linear
Divide-and-Conquer Step (Halving)i = i / 2log2(N) stepsO(log N) Logarithmic
All Element Pairs (Nested)O(1) comparisonN * (N - 1) / 2 stepsO(N^2) Quadratic
All Triplet CombinationsO(1) checkN * (N - 1) * (N - 2) / 6O(N^3) Cubic
Time complexity for common iterative algorithmic structures

Quick Syntax & Reference Sheet

Concept / RuleSyntax / Usage
Enumerate Traversalfor idx, val in enumerate(items): # access both index and item
Triangular Pair Iterationfor i in range(len(arr)): for j in range(i + 1, len(arr)): # all unique pairs (i, j)

Common Pitfalls & Developer Mistakes

✕ Mistake 1:

Modifying a Collection While Iterating Over It

Why it happens:

Correction:
✕ Mistake 2:

Unnecessary Deep Nesting

Why it happens:

Correction:

Frequently Asked Questions

What is the computational difference between range() in Python 2 vs Python 3?

In Python 2, range() allocated a full list of integers in memory (O(N) memory), whereas xrange() was a generator. In Python 3, range() behaves like xrange(), requiring only O(1) auxiliary space.

How do break and continue affect loop control flow?

'break' immediately terminates the innermost enclosing loop and jumps to the code following it. 'continue' halts only the current iteration step and advances the loop counter to the next iteration.
Article Tags:#For Loops#Iterators#Range Generators#Nested Loops#Complexity Analysis
Was this lesson clear and helpful?

Discussion (0)

Sign in to ask questions and reply.
Loading discussion…
Discuss in community