Author: Armin Rigo <[email protected]>
Branch:
Changeset: r57092:6bcaedad2d93
Date: 2012-09-03 11:52 +0200
http://bitbucket.org/pypy/pypy/changeset/6bcaedad2d93/
Log: Rewrite itertools.tee() to use a simple chained list internally,
instead of a list that only ever grows.
diff --git a/pypy/module/itertools/interp_itertools.py
b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -811,7 +811,7 @@
item = data[i] = next()
cnt[0] += 1
else:
- item = data.pop(i)
+ item = data[i] # data.pop(i) if it's the last one
yield item
it = iter(iterable)
return tuple([gen(it.next) for i in range(n)])
@@ -821,47 +821,42 @@
myiter = space.interpclass_w(w_iterable)
if isinstance(myiter, W_TeeIterable): # optimization only
- tee_state = myiter.tee_state
+ chained_list = myiter.chained_list
+ w_iterator = myiter.w_iterator
iterators_w = [w_iterable] * n
for i in range(1, n):
- iterators_w[i] = space.wrap(W_TeeIterable(space, tee_state,
- myiter.index))
+ iterators_w[i] = space.wrap(W_TeeIterable(space, w_iterator,
+ chained_list))
else:
- tee_state = TeeState(space, w_iterable)
- iterators_w = [space.wrap(W_TeeIterable(space, tee_state)) for x in
range(n)]
+ w_iterator = space.iter(w_iterable)
+ chained_list = TeeChainedListNode()
+ iterators_w = [space.wrap(
+ W_TeeIterable(space, w_iterator, chained_list))
+ for x in range(n)]
return space.newtuple(iterators_w)
-class TeeState(object):
- def __init__(self, space, w_iterable):
- self.space = space
- self.w_iterable = self.space.iter(w_iterable)
- self.num_saved = 0
- self.saved_w = []
-
- def get_next(self, index):
- if index >= self.num_saved:
- w_obj = self.space.next(self.w_iterable)
- self.saved_w.append(w_obj)
- self.num_saved += 1
- return w_obj
- else:
- return self.saved_w[index]
+class TeeChainedListNode(object):
+ w_obj = None
class W_TeeIterable(Wrappable):
- def __init__(self, space, tee_state, start_index=0):
+ def __init__(self, space, w_iterator, chained_list):
self.space = space
- self.tee_state = tee_state
- self.index = start_index
+ self.w_iterator = w_iterator
+ assert chained_list is not None
+ self.chained_list = chained_list
def iter_w(self):
return self.space.wrap(self)
def next_w(self):
- try:
- w_obj = self.tee_state.get_next(self.index)
- return w_obj
- finally:
- self.index += 1
+ chained_list = self.chained_list
+ w_obj = chained_list.w_obj
+ if w_obj is None:
+ w_obj = self.space.next(self.w_iterator)
+ chained_list.next = TeeChainedListNode()
+ chained_list.w_obj = w_obj
+ self.chained_list = chained_list.next
+ return w_obj
def W_TeeIterable___new__(space, w_subtype, w_iterable):
# Obscure and undocumented function. PyPy only supports w_iterable
@@ -870,8 +865,8 @@
# semantics are then slightly different; see the XXX in lib-python's
# test_itertools).
myiter = space.interp_w(W_TeeIterable, w_iterable)
- tee_state = myiter.tee_state
- return space.wrap(W_TeeIterable(space, tee_state))
+ return space.wrap(W_TeeIterable(space, myiter.w_iterator,
+ myiter.chained_list))
W_TeeIterable.typedef = TypeDef(
'_tee',
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit