Python - Iterators
What Are Iterators?
An iterator is an object that can be iterated upon, meaning you can traverse through all the values. Technically, an iterator is an object which implements the __iter__() and __next__() methods.
Using iter() and next()
python
# Creating an iterator from a list
numbers = [1, 2, 3]
it = iter(numbers)
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
Custom Iterator Class
You can create your own iterator by defining a class with __iter__() and __next__() methods.
python
class Counter:
def __init__(self, limit):
self.limit = limit
self.count = 0
def __iter__(self):
return self
def __next__(self):
if self.count < self.limit:
self.count += 1
return self.count
else:
raise StopIteration
for num in Counter(3):
print(num)
What Are Generators?
Generators are a simple and concise way to create iterators using functions and the yield keyword. They allow you to iterate lazily (one item at a time) without storing all values in memory.
Creating a Generator with yield
python
# Generator function
def countdown(n):
while n > 0:
yield n
n -= 1
for val in countdown(3):
print(val)
Generator Expressions
Like list comprehensions but using () instead of [], generator expressions are memory-efficient and lazy.
python
# Generator expression
squares = (x*x for x in range(5))
for s in squares:
print(s)
Why Use Iterators and Generators?
- Memory Efficiency: Only one item is in memory at a time.
- Performance: Lazily evaluated, improving speed with large data.
- Cleaner Code: Especially with
yieldor generator expressions.
When to Use?
- Working with large datasets or streams
- Implementing pipelines or custom data flows
- Lazy evaluation required
Pros and Cons
- Pros: Efficient, simple syntax, useful for streams
- Cons: Can only be iterated once, less intuitive debugging