@@ -136,29 +136,6 @@ def get_length(iterable):
136136 return i
137137
138138
139- def product (* args , ** kwargs ):
140- '''
141- Cartesian product of input iterables.
142-
143- Equivalent to nested for-loops in a generator expression. `product(A, B)`
144- returns the same as `((x,y) for x in A for y in B)`.
145-
146- More examples:
147-
148- list(product('ABC', 'xy')) == ['Ax', 'Ay', 'Bx', 'By', 'Cx', 'Cy']
149-
150- list(product(range(2), repeat=2) == ['00', '01', '10', '11']
151-
152- '''
153- # todo: revamp, probably take from stdlib
154- pools = map (tuple , args ) * kwargs .get ('repeat' , 1 )
155- result = [[]]
156- for pool in pools :
157- result = [x + [y ] for x in result for y in pool ]
158- for prod in result :
159- yield tuple (prod )
160-
161-
162139def iter_with (iterable , context_manager ):
163140 '''Iterate on `iterable`, `with`ing the context manager on every `next`.'''
164141
@@ -177,31 +154,6 @@ def iter_with(iterable, context_manager):
177154 yield next_item
178155
179156
180- def izip_longest (* iterables , ** kwargs ):
181- '''
182- izip_longest(iter1 [,iter2 [...]], [fillvalue=None]) -> izip_longest object
183-
184- Return an `izip_longest` object whose `.next()` method returns a `tuple`
185- where the i-th element comes from the i-th iterable argument. The `.next()`
186- method continues until the longest iterable in the argument sequence is
187- exhausted and then it raises `StopIteration`. When the shorter iterables
188- are exhausted, `fillvalue` is substituted in their place. The `fillvalue`
189- defaults to `None` or can be specified by a keyword argument.
190- '''
191- # This is a really obfuscated algorithm, simplify and/or explain
192- fill_value = kwargs .get ('fillvalue' , None )
193- def sentinel (counter = ([fill_value ] * (len (iterables ) - 1 )).pop ):
194- yield counter ()
195- fillers = itertools .repeat (fill_value )
196- iterables = [itertools .chain (iterable , sentinel (), fillers ) for iterable
197- in iterables ]
198- try :
199- for tuple_ in itertools .izip (* iterables ):
200- yield tuple_
201- except IndexError :
202- raise StopIteration
203-
204-
205157def get_items (iterable , n , container_type = tuple ):
206158 '''
207159 Get the next `n` items from the iterable as a `tuple`.
@@ -228,32 +180,27 @@ def double_filter(filter_function, iterable):
228180 true_deque = collections .deque ()
229181 false_deque = collections .deque ()
230182
231- def process_value ():
232- value = next (iterator )
233- if filter_function (value ):
234- true_deque .append (value )
235- else :
236- false_deque .append (value )
237-
238183 def make_true_iterator ():
239184 while True :
240185 try :
241186 yield true_deque .popleft ()
242187 except IndexError :
243- try :
244- process_value ()
245- except StopIteration :
246- break
188+ value = next (iterator ) # `StopIteration` exception recycled.
189+ if filter_function (value ):
190+ yield value
191+ else :
192+ false_deque .append (value )
247193
248194 def make_false_iterator ():
249195 while True :
250196 try :
251197 yield false_deque .popleft ()
252198 except IndexError :
253- try :
254- process_value ()
255- except StopIteration :
256- break
199+ value = next (iterator ) # `StopIteration` exception recycled.
200+ if filter_function (value ):
201+ true_deque .append (value )
202+ else :
203+ yield value
257204
258205 return (make_true_iterator (), make_false_iterator ())
259206
0 commit comments