Python Iterators & Generators
Python Iterators & Generators Interview Questions
What is an iterator in Python?
An iterator is an object that implements the iterator protocol: __iter__() returns itself, and __next__() returns the next item or raises StopIteration. Iterators allow sequential access to elements without loading everything into memory.
What is an iterable in Python?
An iterable is any object that can return an iterator when iter() is called on it. Lists, tuples, strings, dictionaries, sets, and file objects are all iterables. They implement __iter__() method.
What is a generator in Python?
A generator is a special type of iterator created using a function with yield statements. Generators produce values lazily (on-demand) and maintain their state between yields, making them memory-efficient for large datasets.
What is the yield keyword?
yield is used in generator functions to return a value and pause function execution, preserving local state. When called again, execution resumes after the yield. Unlike return, yield doesn't terminate the function.
What is the difference between iterator and generator?
Iterators are classes implementing __iter__() and __next__(). Generators are functions using yield. Generators are simpler to write but less flexible. All generators are iterators, but not all iterators are generators.
How to create a generator expression?
Generator expressions are similar to list comprehensions but use parentheses: (x**2 for x in range(10)). They're memory-efficient as they produce values lazily. No square brackets are used like in list comprehensions.
What is the next() function?
next(iterator[, default]) retrieves the next item from an iterator. Raises StopIteration if no items left, unless default is provided. Example: next(iter([1,2,3])) returns 1.
What is the iter() function?
iter(iterable) returns an iterator object for the iterable. Example: iter([1,2,3]) returns a list iterator. For callable objects, can use two-argument form: iter(callable, sentinel).
What is lazy evaluation in generators?
Lazy evaluation means values are computed only when needed (on-demand), not in advance. Generators use lazy evaluation, saving memory and allowing infinite sequences. Contrast with lists that compute all values upfront.
How to create a custom iterator class?
Define a class with __iter__() returning self, and __next__() returning next value or raising StopIteration. Example: Counter class that counts up to a limit.
What is the difference between generator and list comprehension?
List comprehension [x**2 for x in range(10)] creates a list in memory. Generator expression (x**2 for x in range(10)) creates a generator that yields values lazily. Use generators for memory efficiency.
What is the send() method in generators?
generator.send(value) sends a value into the generator, which becomes the result of the current yield expression. Allows two-way communication between generator and caller. First send must be None or use next().
What is the throw() method in generators?
generator.throw(exception) raises an exception at the point where the generator is paused. Useful for error handling in generators. The generator can catch and handle the exception.
What is the close() method in generators?
generator.close() raises GeneratorExit at the point where generator is paused, allowing cleanup. Generator should catch GeneratorExit and perform cleanup or re-raise it.
What are generator pipelines?
Generator pipelines chain multiple generators together, passing data through a series of transformations. Each generator consumes from previous and produces for next. Memory-efficient for processing large data streams.
What is the itertools module?
itertools provides iterator building blocks for efficient looping. Functions include: count(), cycle(), repeat(), chain(), islice(), groupby(). Useful for advanced iteration patterns.
How to create an infinite generator?
Use while True: loop with yield. Example: def count_from(n): while True: yield n; n += 1. Generators can represent infinite sequences since they produce values lazily.
What is the difference between range() and xrange()?
In Python 2, range() returns a list, xrange() returns a generator-like object. In Python 3, range() behaves like xrange() - returns a range object (immutable sequence type, not a generator but memory-efficient).
What are common use cases for generators?
1. Processing large files line by line
2. Generating infinite sequences
3. Pipeline data processing
4. Memory-efficient data processing
5. Stateful iteration
6. Implementing coroutines
7. Lazy evaluation of expensive computations
2. Generating infinite sequences
3. Pipeline data processing
4. Memory-efficient data processing
5. Stateful iteration
6. Implementing coroutines
7. Lazy evaluation of expensive computations
What is the StopIteration exception?
StopIteration is raised by __next__() when there are no more items to return. For loops catch this exception to terminate. Can provide a value: raise StopIteration(value) (deprecated in Python 3.7+).
Note: Iterators and generators are fundamental to Python's iteration protocol. Generators provide memory-efficient lazy evaluation. Use generator expressions for simple cases, generator functions for complex logic. Remember that generators can only be iterated once - they're exhausted after full iteration. The itertools module provides powerful iterator tools for common patterns.