Log message for revision 118864: back-port c118863 from 2.13 Changed: U Zope/branches/2.12/doc/CHANGES.rst U Zope/branches/2.12/src/Products/ZCatalog/Lazy.py U Zope/branches/2.12/src/Products/ZCatalog/tests/testLazySequences.py
-=- Modified: Zope/branches/2.12/doc/CHANGES.rst =================================================================== --- Zope/branches/2.12/doc/CHANGES.rst 2010-12-14 14:12:11 UTC (rev 118863) +++ Zope/branches/2.12/doc/CHANGES.rst 2010-12-14 14:13:14 UTC (rev 118864) @@ -11,6 +11,7 @@ Bugs Fixed ++++++++++ +- Fix `LazyMap` to avoid unnecessary function calls. 2.12.14 (2010-12-07) -------------------- Modified: Zope/branches/2.12/src/Products/ZCatalog/Lazy.py =================================================================== --- Zope/branches/2.12/src/Products/ZCatalog/Lazy.py 2010-12-14 14:12:11 UTC (rev 118863) +++ Zope/branches/2.12/src/Products/ZCatalog/Lazy.py 2010-12-14 14:13:14 UTC (rev 118864) @@ -134,36 +134,22 @@ 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 + value = data[index] + if value is self._marker: + 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): # Act like a sequence, but get data from a filtering process. # Don't access data until necessary. Only data for which test(data) Modified: Zope/branches/2.12/src/Products/ZCatalog/tests/testLazySequences.py =================================================================== --- Zope/branches/2.12/src/Products/ZCatalog/tests/testLazySequences.py 2010-12-14 14:12:11 UTC (rev 118863) +++ Zope/branches/2.12/src/Products/ZCatalog/tests/testLazySequences.py 2010-12-14 14:13:14 UTC (rev 118864) @@ -98,7 +98,17 @@ 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): return self._createLFilter(lambda x: True, *seq) _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org https://mail.zope.org/mailman/listinfo/zope-checkins