Daniel Schüle wrote: > Hello NG, > > I am wondering if there were proposals or previous disscussions in this > NG considering using 'while' in comprehension lists > > # pseudo code > i=2 > lst=[i**=2 while i<1000] >
You are actually describing two features that list comps don't natively support - while-based termination, and calculating based on prior values of output. Of course there are work-arounds for both, which others have shown. Here's another approach: The while-based termination can be easily achieved using itertools.takewhile, e.g.,: >>> list(itertools.takewhile(lambda x: x < 10, range(100))) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> the harder piece is to access the prior value. One way is like this: def chasetail(start, func): from itertools import tee def mygen(): yield start for i in (func(i) for i in iterators[0]): yield i iterators = tee(mygen()) return iterators[1] the trick is to create two independent iterators, using itertools.tee, one of which is consumed internally in the func(i) for i in iterators[0] generator expression, the other is returned to use code. >>> it = chasetail(2, lambda x: x*x) #careful - this won't terminate >>> it.next() 2 >>> it.next() 4 >>> it.next() 16 >>> it.next() 256 >>> it.next() 65536 >>> Then you can combine these two approaches to get something semantically like what you wanted in the first place (although not as pretty ;-) >>> list(itertools.takewhile(lambda x: x < 1000, chasetail(2, lambda x: x*x))) [2, 4, 16, 256] >>> If you like this sort of thing, you might want to generalize the concept with a Stream class. Here's minimal implementation: import itertools as it class Stream(object): """An extendable stream, that provides a separate iterator (using itertools.tee) on every iteration request""" def __init__(self, *iterables): self.queue = list(iterables) self.itertee = it.tee(self._chain(self.queue))[0] def _chain(self, queue): while queue: for i in self.queue.pop(0): self.head = i yield i def extend(self,other): self.queue.append(other) def __iter__(self): """Normal iteration over the iterables in self.queue in turn""" return self.itertee.__copy__() then, you can write your squaring algorithm as: >>> s= Stream([2]) >>> s.extend(it.takewhile(lambda x: x < 1000, (i**2 for i in s))) >>> list(s) [2, 4, 16, 256] Michael -- http://mail.python.org/mailman/listinfo/python-list