Python Generators Tutorial with Examples

A Python generator is a distinct category of function that produces an iterator object. Rather than providing a single value, it utilizes the yield keyword to deliver a series of values progressively. After each yield expression, the generator pauses its execution, retaining its state across successive iterations.

Generators are designed to be efficient in terms of memory usage, as they produce items incrementally, utilizing the yield keyword to do so.

Python Generators Example

Let us consider a basic example to illustrate the concept of Generators in Python:

Example

Example

def generate_numbers(limit):

    for num in range(1, limit + 1):

        yield num

sequence = generate_numbers(5)

for value in sequence:

    print(value)

Output:

Output

1

2

3

4

5

Explanation:

In the code presented above, a function named generate_numbers is established. This function takes a parameter called limit. Inside the function, a for loop is utilized to iterate through a range starting from 1 and extending to limit + 1, thereby generating the numbers within that range. The function is invoked with an argument of 5 for the limit, resulting in the output of the generated values.

How to Define a Generator in Python?

Creating a generator is straightforward; all you need to do is define a function that includes at least one yield statement within its body. Upon calling this function, rather than receiving a single value, you will obtain a generator object, which acts as an iterator.

Syntax:

Below is the conventional syntax for establishing a generator in Python.

Example

def function(parameters):

	yield statement

Python Generator Example

Let us consider an illustration to showcase the utilization of generators within Python.

Example

Example

def number_generator():

    numbers = [1, 2, 3]

    for num in numbers:

        yield num

# Running the generator to display its output

for item in number_generator():

    print(item)

Output:

Output

1

2

3

Explanation:

The code presented in the example outlines a generator function named 'number_generator' that yields values sequentially from the list [1, 2, 3] utilizing a for loop. Each invocation of the generator function delivers the subsequent value in the order, enabling a more memory-efficient approach by processing the data in a lazy fashion.

Difference between Yield and Return

The yield statement serves a crucial role in generator functions by enabling the generation of a sequence of values progressively. When the yield statement is executed, it halts the function's execution, returns the specified values, and preserves the function's state. This allows the function to resume at the exact point it was paused when it is called again. This feature is particularly advantageous for managing large or complex data streams efficiently.

Conversely, the return statement provides an immediate outcome, yielding a singular final value. Once the return statement is executed, the function concludes, and the local state is not retained. This behavior is particularly advantageous when the function is designed to deliver just one result.

Example

Example

def calculate_total():

    values = [1, 2, 3]

    result = sum(values)

    return result

output = calculate_total()

print(output)

Output:

Explanation:

The function calculate_total generates a collection of numerical values utilizing Python's inherent sum function to compute the aggregate of these numbers. The output of the function is the resultant total, which is then presented. This approach is straightforward, easy to comprehend, and can be readily modified to incorporate additional values.

Python Generator Expression

Generator expressions allow for a more concise form of generators. They resemble lists in functionality but utilize parentheses instead of square brackets, offering enhanced memory efficiency.

Python Generator Expression Example

Let’s consider an example to illustrate the concept of generator expressions in Python.

Example

Example

squares_generator = (num ** 2 for num in range(1, 6))

for square in squares_generator:

    print(square)

Output:

Output

1

4

9

16

25

Explanation:

The code employs a generator expression to produce the squares of a specified number. The generator outputs one square at a time, which is subsequently shown during the iteration of the loop. This approach is memory-efficient since it does not retain the entire list in memory.

Application of Generators in Python

Several applications of generators in Python are as follows:

  • Using a generator to produce a stream of Fibonacci numbers is convenient because to get the next number, you can just call next(x) without worrying about the end of the sequence to interrupt us.
  • For a more common use case of generators, we can also use them to process large data files, like log files, where they can offer a memory-efficient way of handling just the piece we want.
  • Generators can also work as iterators, but are generally faster since you don't have to define the functions for next and iter methods .
  • Conclusion

In Python, generators serve as a powerful tool for handling extensive datasets and producing intricate sequences of results. The yield statement allows a function to yield a single result while preserving its state across successive iterations. This feature proves to be particularly advantageous when dealing with large files or creating infinite sequences such as Fibonacci numbers. When contrasted with a conventional function that merely returns values, generators are advantageous as they can produce a greater amount of data using less memory, thus generating more values within a specified time frame.

Python Generator MCQs

  1. What is the primary purpose of a Python generator?
  • To create classes dynamically
  • To return multiple values from a function
  • To produce a sequence of values lazily using iteration
  • To define decorators
  1. Which keyword is used to define a generator in Python?
  • generate
  • pass
  • return
  • yield
  1. What does a Python generator function return when called?
  • A list
  • A tuple
  • A generator object
  • A single value
  1. Which of the following statements about the yield keyword is TRUE?
  • It pauses the function and saves its state
  • It terminates the function like return
  • It can only be used in list comprehensions
  • It converts a generator into a list

Response: a) It halts the function execution and preserves its current condition.

  1. What will be the result of executing the subsequent code?
  2. Example
    
    def generate():
    
      yield 10
    
      yield 20
    
    for i in generate():
    
      print(i, end=" ")
    
  • 10 10
  • 10 20
  • 20 20
  • Error

Input Required

This code uses input(). Please provide values below: