10 Practical Scenarios of Lazy Evaluation and Infinite Sequences in Python
This article explains lazy evaluation in functional programming and presents ten Python code examples that demonstrate how generators and iterators can efficiently handle infinite sequences and large‑scale data by computing values only when needed.
Lazy evaluation is a key concept in functional programming where computation is deferred until the result is required, providing memory and performance benefits especially for infinite sequences and large data sets.
1. Generating the Fibonacci sequence
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
for i in range(10):
print(next(fib)) # Output: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34Using a generator function allows the Fibonacci sequence to be produced indefinitely without pre‑computing all values.
2. Generating an infinite natural numbers sequence
def natural_numbers():
n = 1
while True:
yield n
n += 1
numbers = natural_numbers()
for i in range(10):
print(next(numbers)) # Output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10This generator yields natural numbers forever, producing each number only when requested.
3. Using a generator expression to process large data
data = [1, 2, 3, 4, 5, ...] # large‑scale data
result = (x * 2 for x in data if x % 2 == 0)
for value in result:
print(value)The generator expression computes each result lazily, avoiding loading the entire dataset into memory.
4. Lazy reading of a large file
def read_large_file(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line
lines = read_large_file('large_file.txt')
for line in lines:
process_line(line)Reading a file line‑by‑line with a generator prevents the whole file from being loaded at once.
5. Generating squares of an infinite sequence
squares = (x**2 for x in natural_numbers())
for i in range(10):
print(next(squares)) # Output: 1, 4, 9, 16, 25, 36, 49, 64, 81, 100The generator expression lazily produces the squares of natural numbers.
6. Lazy prime number filtering
def primes():
primes_list = []
yield 2
for n in natural_numbers():
if all(n % p != 0 for p in primes_list):
primes_list.append(n)
yield n
prime_gen = primes()
for i in range(10):
print(next(prime_gen)) # Output: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29This generator yields prime numbers on demand, calculating each only when needed.
7. Lazy computation of the n‑th Fibonacci number
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
fib_n = fibonacci(10) # Compute only the 10th term
print(fib_n) # Output: 55Only the required term is computed, avoiding the full sequence generation.
8. Lazy processing of elements in an infinite sequence
def process_infinite_sequence(seq):
for item in seq:
process_item(item)
if should_stop(item):
break
infinite_seq = natural_numbers()
process_infinite_sequence(infinite_seq)The loop processes items lazily and can stop early based on a condition.
9. Lazy chunked processing of large data
def process_large_data(data):
chunk_size = 1000
for i in range(0, len(data), chunk_size):
chunk = data[i:i+chunk_size]
process_chunk(chunk)
large_data = [1, 2, 3, 4, 5, ...] # large‑scale data
process_large_data(large_data)Using a generator‑like approach, data is handled in manageable chunks rather than all at once.
10. Lazy accumulation of an infinite sequence
def accumulate(seq):
total = 0
for item in seq:
total += item
yield total
numbers = natural_numbers()
accumulated = accumulate(numbers)
for i in range(10):
print(next(accumulated)) # Output: 1, 3, 6, 10, 15, 21, 28, 36, 45, 55This generator yields the running total of an infinite sequence, computing each sum only when requested.
These examples demonstrate how generators and iterators enable lazy evaluation, allowing efficient handling of infinite sequences and large data sets while conserving memory and computational resources.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.