Commit 813ee8c6 authored by Andreas Zeidler's avatar Andreas Zeidler

fix `LazyMap` to avoid unnecessary function calls when not accessing items in...

fix `LazyMap` to avoid unnecessary function calls when not accessing items in order (fixes http://dev.plone.org/plone/ticket/9018)
parent 10bc33d9
...@@ -11,6 +11,8 @@ http://docs.zope.org/zope2/releases/. ...@@ -11,6 +11,8 @@ http://docs.zope.org/zope2/releases/.
Bugs Fixed Bugs Fixed
++++++++++ ++++++++++
- Fix `LazyMap` to avoid unnecessary function calls.
- LP 686664: WebDAV Lock Manager ZMI view wasn't accessible. - LP 686664: WebDAV Lock Manager ZMI view wasn't accessible.
2.13.1 (2010-12-07) 2.13.1 (2010-12-07)
......
...@@ -145,42 +145,26 @@ class LazyMap(Lazy): ...@@ -145,42 +145,26 @@ class LazyMap(Lazy):
# Don't access data until necessary # Don't access data until necessary
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: if length is not None:
self._len = length self._len=length
else: else:
self._len = len(seq) 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: try:
s = self._seq s=self._seq
except AttributeError: except AttributeError:
return data[index] return data[index]
i = index value = data[index]
if i < 0: if value is self._marker:
i = len(self) + i value = data[index] = self._func(s[index])
if i < 0: return value
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]
class LazyFilter(Lazy): class LazyFilter(Lazy):
......
...@@ -113,6 +113,16 @@ class TestLazyMap(TestLazyCat): ...@@ -113,6 +113,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):
......
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