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/.
Bugs Fixed
++++++++++
- Fix `LazyMap` to avoid unnecessary function calls.
2.12.14 (2010-12-07)
--------------------
......
......@@ -134,35 +134,21 @@ class LazyMap(Lazy):
def __init__(self, func, seq, length=None):
self._seq=seq
self._data=[]
self._func=func
if length is not None: self._len=length
else: self._len = len(seq)
self._marker = object()
self._data = [self._marker] * self._len
def __getitem__(self,index):
data=self._data
try: s=self._seq
except AttributeError: return data[index]
i=index
if i < 0: i=len(self)+i
if i < 0: raise IndexError, index
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]
value = data[index]
if value is self._marker:
value = data[index] = self._func(s[index])
return value
class LazyFilter(Lazy):
# Act like a sequence, but get data from a filtering process.
......
......@@ -98,6 +98,16 @@ class TestLazyMap(TestLazyCat):
lmap = self._createLMap(filter, 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):
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