0
# Iterator and Dictionary Utilities
1
2
Functions for dictionary iteration and general iterator handling that work consistently across Python versions. These utilities provide unified interfaces for dictionary operations and iterator handling that were changed between Python 2 and 3.
3
4
## Capabilities
5
6
### Dictionary Iterator Functions
7
8
Functions that return iterators over dictionary contents, providing consistent behavior across Python versions.
9
10
```python { .api }
11
def iterkeys(d: dict, **kw) -> Iterator[Any]
12
"""Return iterator over dictionary keys."""
13
14
def itervalues(d: dict, **kw) -> Iterator[Any]
15
"""Return iterator over dictionary values."""
16
17
def iteritems(d: dict, **kw) -> Iterator[tuple[Any, Any]]
18
"""Return iterator over dictionary items as (key, value) pairs."""
19
20
def iterlists(d: dict, **kw) -> Iterator[list[Any]]
21
"""Return iterator over dictionary lists (for MultiDict-like objects)."""
22
```
23
24
**Parameters:**
25
- `d`: Dictionary to iterate over
26
- `**kw`: Additional keyword arguments forwarded to the underlying dictionary method
27
28
**Usage Examples:**
29
30
```python
31
import six
32
33
data = {"a": 1, "b": 2, "c": 3}
34
35
# Iterate over keys
36
for key in six.iterkeys(data):
37
print(key) # Prints: a, b, c
38
39
# Iterate over values
40
for value in six.itervalues(data):
41
print(value) # Prints: 1, 2, 3
42
43
# Iterate over items
44
for key, value in six.iteritems(data):
45
print(f"{key}: {value}") # Prints: a: 1, b: 2, c: 3
46
47
# Memory efficient iteration over large dictionaries
48
large_dict = {str(i): i for i in range(10000)}
49
for key, value in six.iteritems(large_dict):
50
if value > 5000:
51
break
52
```
53
54
### Dictionary View Functions
55
56
Functions that return dictionary views (Python 3 behavior) or equivalent iterators (Python 2).
57
58
```python { .api }
59
def viewkeys(d: dict) -> Any
60
"""Return dictionary keys view."""
61
62
def viewvalues(d: dict) -> Any
63
"""Return dictionary values view."""
64
65
def viewitems(d: dict) -> Any
66
"""Return dictionary items view."""
67
```
68
69
**Usage Examples:**
70
71
```python
72
import six
73
74
data = {"a": 1, "b": 2, "c": 3}
75
76
# Get keys view/equivalent
77
keys_view = six.viewkeys(data)
78
print("a" in keys_view) # True
79
80
# Get values view/equivalent
81
values_view = six.viewvalues(data)
82
print(1 in values_view) # True
83
84
# Get items view/equivalent
85
items_view = six.viewitems(data)
86
print(("a", 1) in items_view) # True
87
88
# Set operations on views (Python 3 behavior)
89
dict1 = {"a": 1, "b": 2}
90
dict2 = {"b": 2, "c": 3}
91
common_keys = six.viewkeys(dict1) & six.viewkeys(dict2) # {'b'}
92
```
93
94
### Iterator Utilities
95
96
General utilities for working with iterators across Python versions.
97
98
```python { .api }
99
def advance_iterator(it: Iterator) -> Any
100
"""Advance an iterator by one step and return the next value."""
101
102
def next(it: Iterator, default: Any = None) -> Any
103
"""Get next item from iterator with optional default."""
104
105
def callable(obj: Any) -> bool
106
"""Test if an object is callable."""
107
```
108
109
**Usage Examples:**
110
111
```python
112
import six
113
114
# Advance iterator manually
115
data = iter([1, 2, 3, 4, 5])
116
first = six.advance_iterator(data) # 1
117
second = six.next(data) # 2
118
119
# Use with default value
120
empty_iter = iter([])
121
value = six.next(empty_iter, "default") # "default"
122
123
# Test callability
124
def my_function():
125
pass
126
127
print(six.callable(my_function)) # True
128
print(six.callable("string")) # False
129
print(six.callable(lambda x: x)) # True
130
```
131
132
### Iterator Base Class
133
134
Base class for creating cross-version compatible iterators.
135
136
```python { .api }
137
class Iterator:
138
"""Base iterator class for Python 2 compatibility."""
139
def __iter__(self) -> Iterator
140
def __next__(self) -> Any
141
```
142
143
This class provides the correct iterator protocol for both Python versions, handling the `__next__` vs `next` method difference.
144
145
**Usage Example:**
146
147
```python
148
import six
149
150
class CountdownIterator(six.Iterator):
151
def __init__(self, start):
152
self.start = start
153
154
def __iter__(self):
155
return self
156
157
def __next__(self):
158
if self.start <= 0:
159
raise StopIteration
160
self.start -= 1
161
return self.start + 1
162
163
# Use the iterator
164
countdown = CountdownIterator(3)
165
for num in countdown:
166
print(num) # Prints: 3, 2, 1
167
```
168
169
### Method and Function Introspection
170
171
Functions for accessing method and function attributes consistently across Python versions.
172
173
```python { .api }
174
def get_method_function(method: Any) -> Any
175
"""Get function from method object."""
176
177
def get_method_self(method: Any) -> Any
178
"""Get self from method object."""
179
180
def get_function_closure(func: Any) -> Any
181
"""Get closure from function object."""
182
183
def get_function_code(func: Any) -> Any
184
"""Get code object from function."""
185
186
def get_function_defaults(func: Any) -> Any
187
"""Get defaults from function object."""
188
189
def get_function_globals(func: Any) -> Any
190
"""Get globals from function object."""
191
```
192
193
**Usage Examples:**
194
195
```python
196
import six
197
198
class MyClass:
199
def my_method(self, x, y=10):
200
z = x + y
201
return lambda: z
202
203
obj = MyClass()
204
method = obj.my_method
205
206
# Access method components
207
func = six.get_method_function(method) # Unbound function
208
self_obj = six.get_method_self(method) # The instance (obj)
209
210
# Access function components
211
code = six.get_function_code(func) # Code object
212
defaults = six.get_function_defaults(func) # (10,)
213
globals_dict = six.get_function_globals(func) # Global namespace
214
215
# Example with closure
216
closure_func = obj.my_method(5)
217
closure = six.get_function_closure(closure_func) # Closure variables
218
```
219
220
### Method Creation Utilities
221
222
Functions for creating bound and unbound methods across Python versions.
223
224
```python { .api }
225
def get_unbound_function(func: Any) -> Any
226
"""Get function from possibly unbound function."""
227
228
def create_bound_method(func: Callable, instance: Any) -> Any
229
"""Create a bound method from function and instance."""
230
231
def create_unbound_method(func: Callable, cls: type) -> Any
232
"""Create an unbound method from function and class."""
233
```
234
235
**Usage Examples:**
236
237
```python
238
import six
239
240
class MyClass:
241
def my_method(self):
242
return "Hello from method"
243
244
# Get unbound function
245
unbound = six.get_unbound_function(MyClass.my_method)
246
247
# Create bound method manually
248
instance = MyClass()
249
bound_method = six.create_bound_method(unbound, instance)
250
result = bound_method() # "Hello from method"
251
252
# Create unbound method (primarily for Python 2 compatibility)
253
unbound_method = six.create_unbound_method(unbound, MyClass)
254
```
255
256
## Common Usage Patterns
257
258
```python
259
import six
260
261
# Efficient dictionary processing
262
def process_large_dict(data_dict):
263
"""Process dictionary without creating intermediate lists."""
264
result = {}
265
266
# Memory-efficient iteration
267
for key, value in six.iteritems(data_dict):
268
if isinstance(value, six.string_types):
269
result[key] = value.upper()
270
elif six.callable(value):
271
result[key] = value()
272
else:
273
result[key] = str(value)
274
275
return result
276
277
# Custom iterator with cross-version compatibility
278
class ChunkedIterator(six.Iterator):
279
"""Iterator that yields chunks of data."""
280
281
def __init__(self, data, chunk_size):
282
self.data = iter(data)
283
self.chunk_size = chunk_size
284
285
def __iter__(self):
286
return self
287
288
def __next__(self):
289
chunk = []
290
try:
291
for _ in range(self.chunk_size):
292
chunk.append(six.next(self.data))
293
except StopIteration:
294
if chunk:
295
return chunk
296
raise
297
return chunk
298
299
# Use chunked iterator
300
data = range(10)
301
chunked = ChunkedIterator(data, 3)
302
for chunk in chunked:
303
print(chunk) # [0, 1, 2], [3, 4, 5], [6, 7, 8], [9]
304
305
# Method introspection and modification
306
def analyze_methods(cls):
307
"""Analyze all methods in a class."""
308
methods_info = {}
309
310
for name in dir(cls):
311
attr = getattr(cls, name)
312
if six.callable(attr) and hasattr(attr, '__func__'):
313
func = six.get_method_function(attr) if hasattr(attr, '__self__') else attr
314
methods_info[name] = {
315
'defaults': six.get_function_defaults(func),
316
'code': six.get_function_code(func),
317
'arg_count': six.get_function_code(func).co_argcount
318
}
319
320
return methods_info
321
```