genexp surprise (wart?)
Ben Cartwright
bencvt at gmail.com
Fri May 26 01:23:02 EDT 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 = stream.next()
> 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...
http://www.python.org/doc/faq/programming/#what-are-the-rules-for-local-and-global-variables-in-python
...Python treats p in the genexp as a non-local variable.
--Ben
More information about the Python-list
mailing list