Generators/iterators, Pythonicity, and primes

Kay Schluehr kay.schluehr at gmx.net
Sun Apr 5 17:37:20 CEST 2009


On 5 Apr., 17:14, John Posner <jjpos... at snet.net> wrote:
> Kay Schluehr said:
>
>  > g = (lambda primes = []:
>  >       (n for n in count(2) \
>  >          if
>  >              (lambda n, primes: (n in primes if primes and
> n<=primes[-1] \
>  >          else
>  >              (primes.append(n) or True \
>  >                  if all(n%p for p in primes if p <= sqrt(n)) \
>  >                  else False)))(n, primes)))()
>
> Um ... did you say "easy"? :-) This is prodigious, and it's definitely a
> solution to the generator-expression-only challenge I laid down.

That's because it is *one* expression. The avoidance of named
functions makes it look obfuscated or prodigious. Once it is properly
dissected it doesn't look that amazing anymore.

Start with:

(n for n in count(2) if is_prime(n, primes))

The is_prime function has following implementation:

def is_prime(n, primes):
    if primes and n<=primes[-1]:
        return n in primes
    else:
        if all(n%p for p in primes if p <= sqrt(n)):
            primes.append(n)
            return True
        else:
            return False

But we need a lambda-fied function expression instead of the function
definition. This yields:

is_prime = lambda n, primes: (n in primes \
        if primes and n<=primes[-1] \
        else (primes.append(n) or True \
        if all(n%p for p in primes if p <= sqrt(n)) \
        else False))

Finally the trick with primes definition within an expression by means
of an optional argument in the lambda is applied.


> But I
> think this is a case in which using a generator expression causes a loss
> in "Pythonicity", rather than a gain. Many, many thanks for this!

I think so too. The solution with the simple generator expression and
the fully defined is_prime function may be just adequate.



More information about the Python-list mailing list