Python Advanced Concepts Generators Tutorial
Intermediate Level Memory Efficient

Python Generators: Complete Guide with Examples

Master Python generators - powerful tools for creating memory-efficient iterators using the yield keyword. Learn generator functions, expressions, coroutines, and handle large datasets with lazy evaluation.

yield Keyword

Core generator feature

30+ Examples

Practical generator patterns

Memory Efficient

Lazy evaluation

Infinite Sequences

Stream processing

What is a Generator?

A generator is a special type of function that returns values one at a time instead of returning all values at once.

Generators use the keyword: yield

Why Use Generators?

Generators are useful because they:

  • Save memory
  • Work faster for large data
  • Produce values lazily (on demand)
  • Simplify iterator creation

Normal Function vs Generator

Normal Function
def numbers():
    return [1, 2, 3]

print(numbers())

Output: [1, 2, 3]

Generator Function
def numbers():
    yield 1
    yield 2
    yield 3

print(numbers())

Output: <generator object numbers at 0x...>

Accessing Generator Values

Use: next() and loops.

Using next()
def demo():
    yield 10
    yield 20
    yield 30

g = demo()

print(next(g))
print(next(g))
print(next(g))

Output:
10
20
30

What Happens Internally?

When yield executes:

  • Function pauses
  • State is saved
  • Resumes from same point next time

Generator with Loop

def count():
    for i in range(5):
        yield i

g = count()

for value in g:
    print(value)

Output:
0
1
2
3
4

Difference Between return and yield

returnyield
Ends functionPauses function
Returns single valueReturns sequence one-by-one
Uses more memoryMemory efficient

Generator Expression

Similar to list comprehension.

List Comprehension
nums = [x*x for x in range(5)]
print(nums)

Output: [0, 1, 4, 9, 16]

Generator Expression
nums = (x*x for x in range(5))

print(nums)

for i in nums:
    print(i)

Output:
<generator object ...>
0
1
4
9
16

Memory Comparison

Generators are memory efficient because they do not store all values at once.

Infinite Generators

Generators can generate infinite values.

Example:
def infinite():
    n = 1

    while True:
        yield n
        n += 1

g = infinite()

print(next(g))
print(next(g))
print(next(g))

Output:
1
2
3

Fibonacci Using Generator

def fibonacci(n):
    a, b = 0, 1

    for i in range(n):
        yield a
        a, b = b, a + b

for num in fibonacci(10):
    print(num)

Output:
0
1
1
2
3
5
8
13
21
34

Generator for Reading Large Files

def read_file(file_name):
    with open(file_name) as file:
        for line in file:
            yield line

for line in read_file("data.txt"):
    print(line)

Advantages of Generators

  • Faster execution
  • Reduced memory usage
  • Useful for large datasets
  • Supports lazy evaluation
  • Easy iterator implementation

Disadvantages of Generators

  • Can iterate only once
  • Slightly harder to debug
  • Values are not stored permanently

Iterators vs Generators

IteratorGenerator
Created using classCreated using function
Uses __iter__() and __next__()Uses yield
More complexSimpler

Comparison Table

Feature Iterator Generator Decorator
Purpose Loop protocol Easy iteration Modify functions
Implementation Class with __next__ Function with yield Function returning wrapper
Memory Efficient Very efficient Minimal overhead
Use case Custom iteration Lazy evaluation Cross-cutting concerns
State Manual management Automatic suspension Wraps existing code

Real-Life Example

Music Streaming App

Songs are loaded one-by-one instead of loading all songs into memory.

This is similar to generators.

Next Topics: We'll cover Python zip() and enumerate() for cleaner loops and aligned iteration