Additional building blocks, recipes, and routines for working with Python iterables beyond itertools.
—
Advanced iterator wrappers that provide peek and seek capabilities.
Iterator wrapper that allows looking ahead without consuming items.
class peekable:
"""
Iterator wrapper that allows peeking ahead.
Provides methods to look at upcoming items without consuming them
and to prepend items back to the iterator.
"""
def __init__(self, iterable):
"""Initialize with an iterable."""
def __iter__(self):
"""Return self as iterator."""
def __next__(self):
"""Return next item from iterator."""
def peek(self, default=None):
"""
Return next item without consuming it.
Args:
default: Value to return if iterator is exhausted
Returns:
Next item or default if exhausted
"""
def prepend(self, *values):
"""
Prepend values to be yielded before continuing iteration.
Args:
*values: Values to prepend
"""
def __bool__(self):
"""Return True if iterator has more items."""Usage Examples:
from more_itertools import peekable
# Basic peeking
p = peekable([1, 2, 3, 4, 5])
print(p.peek()) # 1 (not consumed)
print(p.peek()) # 1 (still not consumed)
print(next(p)) # 1 (now consumed)
print(p.peek()) # 2
# Peek with default
p = peekable([])
print(p.peek('empty')) # 'empty'
# Prepending values
p = peekable([3, 4, 5])
p.prepend(1, 2)
list(p) # [1, 2, 3, 4, 5]
# Check if iterator has items
p = peekable([1, 2, 3])
while p:
print(next(p))Iterator wrapper that allows seeking to specific positions.
class seekable:
"""
Iterator wrapper that allows seeking to arbitrary positions.
Caches items as they are consumed to enable seeking backwards.
"""
def __init__(self, iterable):
"""Initialize with an iterable."""
def __iter__(self):
"""Return self as iterator."""
def __next__(self):
"""Return next item from iterator."""
def seek(self, index):
"""
Seek to absolute position in iterator.
Args:
index: Position to seek to (0-based)
"""
def relative_seek(self, count):
"""
Seek relative to current position.
Args:
count: Number of positions to move (can be negative)
"""
@property
def index(self):
"""Current position in the iterator."""Usage Examples:
from more_itertools import seekable
# Basic seeking
s = seekable([10, 20, 30, 40, 50])
print(next(s)) # 10
print(next(s)) # 20
s.seek(0) # Go back to start
print(next(s)) # 10
s.seek(4) # Jump to position 4
print(next(s)) # 50
# Relative seeking
s = seekable([1, 2, 3, 4, 5])
next(s), next(s) # Consume 1, 2 (now at position 2)
s.relative_seek(-1) # Go back one position
print(next(s)) # 2
# Check current position
s = seekable([1, 2, 3])
next(s)
print(s.index) # 1Look ahead at the beginning of an iterable.
def spy(iterable, n=1):
"""
Return first n items and an iterator for the full sequence.
Args:
iterable: Input iterable to spy on
n: Number of items to peek at (default 1)
Returns:
Tuple of (first_n_items, full_iterator)
"""Usage Examples:
from more_itertools import spy
# Spy on first item
first_items, iterator = spy([1, 2, 3, 4, 5])
print(first_items) # [1]
print(list(iterator)) # [1, 2, 3, 4, 5]
# Spy on first 3 items
first_three, iterator = spy([1, 2, 3, 4, 5], 3)
print(first_three) # [1, 2, 3]
print(list(iterator)) # [1, 2, 3, 4, 5]
# Use for conditional processing
data = range(1000)
preview, full_data = spy(data, 10)
if max(preview) > 5:
# Process large numbers differently
result = process_large_numbers(full_data)
else:
result = process_small_numbers(full_data)Install with Tessl CLI
npx tessl i tessl/pypi-more-itertools