genexp surprise (wart?)

Ben Cartwright bencvt at
Fri May 26 07:23:02 CEST 2006

Paul Rubin wrote:
> I tried to code the Sieve of Erastosthenes with generators:
>     def sieve_all(n = 100):
>         # yield all primes up to n
>         stream = iter(xrange(2, n))
>         while True:
>             p =
>             yield p
>             # filter out all multiples of p from stream
>             stream = (q for q in stream if q%p != 0)
>     # print primes up to 100
>     print list(sieve_all(100))
> but it didn't work.  I had to replace
>             stream = (q for q in stream if q%p != 0)
> with
>         def s1(p):
>             return (q for q in stream if q%p != 0)
>         stream = s1(p)
> or alternatively
>         stream = (lambda p,stream: \
>                     (q for q in stream if q%p != 0)) (p, stream)

You do realize that you're creating a new level of generator nesting
with each iteration of the while loop, right?  You will quickly hit the
maximum recursion limit.  Try generating the first 1000 primes.

> I had thought that genexps worked like that automatically, i.e. the
> stuff inside the genexp was in its own scope.  If it's not real
> obvious what's happening instead, that's a sign that the current
> behavior is a wart.  (The problem is that p in my first genexp comes
> from the outer scope, and changes as the sieve iterates through the
> stream)

I don't see how it's a wart.  p is accessed (i.e., not set) by the
genexp.  Consistent with the function scoping rules in...
...Python treats p in the genexp as a non-local variable.


More information about the Python-list mailing list