7.1 - Iterators
7.1.1 - Introduction
Iterators are a fundamental concept in Python, allowing for efficient and straightforward iteration over collections like lists, tuples, and dictionaries. They are objects that can be iterated upon, meaning you can traverse through all the values. Python iterator objects must implement two special methods, __iter__()
and __next__()
, collectively known as the iterator protocol.
7.1.2 - Basic Syntax of Iterators
An iterator in Python is any Python object that can be used with a for in
loop. Python iterates over these objects using two built-in functions:
iter(object)
: This method is used to convert an iterable to an iterator.next(iterator)
: This method returns the next item from the iterator.
my_list = [1, 2, 3, 4]
my_iter = iter(my_list)
print(next(my_iter)) # Output: 1
print(next(my_iter)) # Output: 2
7.1.3 - Creating Your Own Iterator
To create an iterator from scratch, you need to implement the methods __iter__()
and __next__()
in your object.
class CountDown:
def __init__(self, start):
self.current = start
def __iter__(self):
return self
def __next__(self):
if self.current <= 0:
raise StopIteration
else:
self.current -= 1
return self.current + 1
# Example usage
for number in CountDown(3):
print(number)
7.1.4 - Iterators Case Studies
7.1.4.1 - Case Study 1: Infinite Iterator
Here we create an iterator that generates an infinite sequence of numbers.
class InfiniteNumbers:
def __init__(self):
self.number = 0
def __iter__(self):
return self
def __next__(self):
self.number += 1
return self.number
# Example usage
infinite = InfiniteNumbers()
print(next(infinite)) # Output: 1
print(next(infinite)) # Output: 2
7.1.4.2 - Case Study 2: Fibonacci Iterator
This iterator generates numbers in the Fibonacci sequence.
class Fibonacci:
def __init__(self):
self.prev, self.curr = 0, 1
def __iter__(self):
return self
def __next__(self):
value = self.curr
self.prev, self.curr = self.curr, self.prev + self.curr
return value
# Example usage
fib = Fibonacci()
for _ in range(5):
print(next(fib)) # Output: 1, 1, 2, 3, 5
7.1.4.3 - Case Study 3: Reverse Iterator
This iterator reverses a given sequence. It demonstrates how to traverse a collection in the reverse order using an iterator.
class Reverse:
def __init__(self, sequence):
self.sequence = sequence
self.index = len(sequence)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index -= 1
return self.sequence[self.index]
# Example usage
rev = Reverse([1, 2, 3, 4])
for item in rev:
print(item) # Output: 4, 3, 2, 1
7.1.4.4 - Case Study 4: File Lines Iterator
This iterator reads lines from a file without loading the entire file into memory. It's useful for processing large files.
class FileLines:
def __init__(self, filename):
self.file = open(filename, 'r')
def __iter__(self):
return self
def __next__(self):
line = self.file.readline()
if not line:
self.file.close()
raise StopIteration
return line.strip()
# Example usage
file_lines = FileLines('example.txt')
for line in file_lines:
print(line)
7.1.4.5 - Case Study 5: Prime Numbers Iterator
This iterator generates an indefinite sequence of prime numbers, showcasing the use of iterators for mathematical sequences.
class PrimeNumbers:
def __init__(self):
self.current = 2
def __iter__(self):
return self
def __next__(self):
while True:
is_prime = all(self.current % num != 0 for num in range(2, int(self.current ** 0.5) + 1))
if is_prime:
prime = self.current
self.current += 1
return prime
self.current += 1
# Example usage
primes = PrimeNumbers()
for _ in range(5):
print(next(primes)) # Output: 2, 3, 5, 7, 11