Commit 410714c3 authored by Andreas Zeidler's avatar Andreas Zeidler

back-port c118863 from 2.13

parent 6a88eb97
...@@ -11,6 +11,7 @@ http://docs.zope.org/zope2/releases/. ...@@ -11,6 +11,7 @@ http://docs.zope.org/zope2/releases/.
Bugs Fixed Bugs Fixed
++++++++++ ++++++++++
- Fix `LazyMap` to avoid unnecessary function calls.
2.12.14 (2010-12-07) 2.12.14 (2010-12-07)
-------------------- --------------------
......
...@@ -134,35 +134,21 @@ class LazyMap(Lazy): ...@@ -134,35 +134,21 @@ class LazyMap(Lazy):
def __init__(self, func, seq, length=None): def __init__(self, func, seq, length=None):
self._seq=seq self._seq=seq
self._data=[]
self._func=func self._func=func
if length is not None: self._len=length if length is not None: self._len=length
else: self._len = len(seq) else: self._len = len(seq)
self._marker = object()
self._data = [self._marker] * self._len
def __getitem__(self,index): def __getitem__(self,index):
data=self._data data=self._data
try: s=self._seq try: s=self._seq
except AttributeError: return data[index] except AttributeError: return data[index]
i=index value = data[index]
if i < 0: i=len(self)+i if value is self._marker:
if i < 0: raise IndexError, index value = data[index] = self._func(s[index])
return value
ind=len(data)
if i < ind: return data[i]
ind=ind-1
func=self._func
while i > ind:
try:
ind=ind+1
data.append(func(s[ind]))
except IndexError:
del self._func
del self._seq
raise IndexError, index
return data[i]
class LazyFilter(Lazy): class LazyFilter(Lazy):
# Act like a sequence, but get data from a filtering process. # Act like a sequence, but get data from a filtering process.
......
...@@ -98,6 +98,16 @@ class TestLazyMap(TestLazyCat): ...@@ -98,6 +98,16 @@ class TestLazyMap(TestLazyCat):
lmap = self._createLMap(filter, seq1, seq2, seq3) lmap = self._createLMap(filter, seq1, seq2, seq3)
self._compare(lmap, [str(x).lower() for x in (seq1 + seq2 + seq3)]) self._compare(lmap, [str(x).lower() for x in (seq1 + seq2 + seq3)])
def testMapFuncIsOnlyCalledAsNecessary(self):
seq = range(10)
count = [0] # closure only works with list, and `nonlocal` in py3
def func(x):
count[0] += 1
return x
lmap = self._createLMap(func, seq)
self.assertEqual(lmap[5], 5)
self.assertEqual(count[0], 1)
class TestLazyFilter(TestLazyCat): class TestLazyFilter(TestLazyCat):
def _createLSeq(self, *seq): def _createLSeq(self, *seq):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment