0
# Lookahead and Lookback
1
2
Advanced iterator wrappers that provide peek and seek capabilities.
3
4
## Capabilities
5
6
### Peekable Iterator
7
8
Iterator wrapper that allows looking ahead without consuming items.
9
10
```python { .api }
11
class peekable:
12
"""
13
Iterator wrapper that allows peeking ahead.
14
15
Provides methods to look at upcoming items without consuming them
16
and to prepend items back to the iterator.
17
"""
18
19
def __init__(self, iterable):
20
"""Initialize with an iterable."""
21
22
def __iter__(self):
23
"""Return self as iterator."""
24
25
def __next__(self):
26
"""Return next item from iterator."""
27
28
def peek(self, default=None):
29
"""
30
Return next item without consuming it.
31
32
Args:
33
default: Value to return if iterator is exhausted
34
35
Returns:
36
Next item or default if exhausted
37
"""
38
39
def prepend(self, *values):
40
"""
41
Prepend values to be yielded before continuing iteration.
42
43
Args:
44
*values: Values to prepend
45
"""
46
47
def __bool__(self):
48
"""Return True if iterator has more items."""
49
```
50
51
**Usage Examples:**
52
53
```python
54
from more_itertools import peekable
55
56
# Basic peeking
57
p = peekable([1, 2, 3, 4, 5])
58
print(p.peek()) # 1 (not consumed)
59
print(p.peek()) # 1 (still not consumed)
60
print(next(p)) # 1 (now consumed)
61
print(p.peek()) # 2
62
63
# Peek with default
64
p = peekable([])
65
print(p.peek('empty')) # 'empty'
66
67
# Prepending values
68
p = peekable([3, 4, 5])
69
p.prepend(1, 2)
70
list(p) # [1, 2, 3, 4, 5]
71
72
# Check if iterator has items
73
p = peekable([1, 2, 3])
74
while p:
75
print(next(p))
76
```
77
78
### Seekable Iterator
79
80
Iterator wrapper that allows seeking to specific positions.
81
82
```python { .api }
83
class seekable:
84
"""
85
Iterator wrapper that allows seeking to arbitrary positions.
86
87
Caches items as they are consumed to enable seeking backwards.
88
"""
89
90
def __init__(self, iterable):
91
"""Initialize with an iterable."""
92
93
def __iter__(self):
94
"""Return self as iterator."""
95
96
def __next__(self):
97
"""Return next item from iterator."""
98
99
def seek(self, index):
100
"""
101
Seek to absolute position in iterator.
102
103
Args:
104
index: Position to seek to (0-based)
105
"""
106
107
def relative_seek(self, count):
108
"""
109
Seek relative to current position.
110
111
Args:
112
count: Number of positions to move (can be negative)
113
"""
114
115
@property
116
def index(self):
117
"""Current position in the iterator."""
118
```
119
120
**Usage Examples:**
121
122
```python
123
from more_itertools import seekable
124
125
# Basic seeking
126
s = seekable([10, 20, 30, 40, 50])
127
print(next(s)) # 10
128
print(next(s)) # 20
129
s.seek(0) # Go back to start
130
print(next(s)) # 10
131
s.seek(4) # Jump to position 4
132
print(next(s)) # 50
133
134
# Relative seeking
135
s = seekable([1, 2, 3, 4, 5])
136
next(s), next(s) # Consume 1, 2 (now at position 2)
137
s.relative_seek(-1) # Go back one position
138
print(next(s)) # 2
139
140
# Check current position
141
s = seekable([1, 2, 3])
142
next(s)
143
print(s.index) # 1
144
```
145
146
### Spy Function
147
148
Look ahead at the beginning of an iterable.
149
150
```python { .api }
151
def spy(iterable, n=1):
152
"""
153
Return first n items and an iterator for the full sequence.
154
155
Args:
156
iterable: Input iterable to spy on
157
n: Number of items to peek at (default 1)
158
159
Returns:
160
Tuple of (first_n_items, full_iterator)
161
"""
162
```
163
164
**Usage Examples:**
165
166
```python
167
from more_itertools import spy
168
169
# Spy on first item
170
first_items, iterator = spy([1, 2, 3, 4, 5])
171
print(first_items) # [1]
172
print(list(iterator)) # [1, 2, 3, 4, 5]
173
174
# Spy on first 3 items
175
first_three, iterator = spy([1, 2, 3, 4, 5], 3)
176
print(first_three) # [1, 2, 3]
177
print(list(iterator)) # [1, 2, 3, 4, 5]
178
179
# Use for conditional processing
180
data = range(1000)
181
preview, full_data = spy(data, 10)
182
if max(preview) > 5:
183
# Process large numbers differently
184
result = process_large_numbers(full_data)
185
else:
186
result = process_small_numbers(full_data)
187
```