Python > Advanced Python Concepts > Iterators and Generators > Creating Custom Iterators
Custom Iterator for a Range with a Step
Demonstrates how to create a custom iterator that mimics the functionality of Python's built-in range()
function but allows for custom step values and more control over the iteration process. This iterator generates a sequence of numbers within a specified range, incrementing by a given step value.
Code Implementation
This code defines a class CustomRangeIterator
that simulates the behavior of the range()
function. The __init__
method initializes the start, stop, and step values. It also handles the case where the step is zero or the range is empty. The __iter__
method returns the iterator itself. The __next__
method calculates the next value in the sequence based on the step and returns it. When the end of the range is reached, it raises StopIteration
.
class CustomRangeIterator:
def __init__(self, start, stop, step=1):
self.start = start
self.stop = stop
self.step = step
self.current = start
if step == 0:
raise ValueError("Step cannot be zero")
if step > 0 and start >= stop:
self.current = stop # Empty range
elif step < 0 and start <= stop:
self.current = stop # Empty range
def __iter__(self):
return self
def __next__(self):
if self.step > 0 and self.current < self.stop:
value = self.current
self.current += self.step
return value
elif self.step < 0 and self.current > self.stop:
value = self.current
self.current += self.step
return value
else:
raise StopIteration
# Example Usage:
custom_range = CustomRangeIterator(1, 10, 2)
for num in custom_range:
print(num)
custom_range_negative = CustomRangeIterator(10, 1, -2)
for num in custom_range_negative:
print(num)
Concepts Behind the Snippet
This example reinforces the concepts of iterators by providing a practical use case: implementing a range-like functionality. It demonstrates how to maintain internal state (self.current
) to track the current position within the sequence and how to handle different scenarios, such as positive and negative step values.
Real-Life Use Case
This type of iterator can be used in scenarios where you need to iterate over a sequence of numbers with a specific step value, such as processing data in batches or generating a sequence of timestamps. It can also be extended to handle more complex range-like operations, such as generating a sequence of dates with a specific interval.
Best Practices
Interview Tip
Be prepared to discuss the advantages and disadvantages of using custom iterators compared to built-in functions like range()
. Emphasize the flexibility and control that custom iterators provide.
When to Use Them
Use this custom iterator when you need a range-like sequence with more control over the iteration process, especially when you need to handle edge cases or perform additional computations within the iterator.
Memory Footprint
Similar to the Fibonacci example, this iterator is memory-efficient because it generates values on demand.
Alternatives
The built-in range()
function can be used for simple range generation. However, custom iterators provide more flexibility for handling complex scenarios.
Pros
Cons
range()
function.
FAQ
-
What happens if I provide a step value of 0?
The code raises aValueError
to prevent division by zero errors during iteration. -
How does this differ from the built-in
range()
function?
The built-inrange()
function is more concise for simple range generation. However, this custom iterator provides more flexibility for handling complex scenarios and custom step values, including edge cases. -
Can I use floating-point numbers for the start, stop, and step values?
While the code would technically work with floats, it's generally not recommended due to potential precision issues with floating-point arithmetic. It's best to stick to integers for well-defined ranges.