[Python-ideas] Is this PEP-able? for X in ListY while conditionZ:
Shane Green
shane at umbrellacode.com
Mon Jul 1 17:21:24 CEST 2013
Having a bit of a hard time following the status of this as I dropped out for a while, but I’m not really for the semi-colon separator approach. Of all the options already available in list comprehensions, this one actually seems to be one of the most easily because it starts with a keyword and ends at the end. Not that syntax highlighting should be taken into account in general, it’s worth noting the syntax highlighted version really makes this distinction quite clear:
One thing I could see doing would be to allow semi-colons anywhere in a list comprehension that’s a boundary between statements of the expanded form.
Then they behave just like the optional semi-colons you could put at the end of a line.
Sorry if that’s precisely what’s been promoted. .
On Jul 1, 2013, at 4:57 AM, Oscar Benjamin <oscar.j.benjamin at gmail.com> wrote:
> On 30 June 2013 00:51, Nick Coghlan <ncoghlan at gmail.com> wrote:
>> [x for x in iterable; break if x is None]
>> [x for x in data if x; break if x is None]
>>
>> One nice advantage of that notation is that:
>>
>> 1. The statement after the ";" is exactly the statement that would
>> appear in the expanded loop
>> 2. It can be combined unambiguously with a filtering clause
>> 3. It clearly disallows its use with nested loops in the comprehension
>
> It has the significant disadvantage that Steven pointed out which is
> that it doesn't read very well. The most important aspect of a
> comprehension is its comprehensibility. Consider getting the prime
> numbers less than 100:
>
> primes100 = {p for p in primes(); break if p >= 100}
>
> You need to invert the if condition to understand which primes are in
> the resulting set. With for/while it reads properly and the condition
> at the right expresses a true property of the elements in the
> resulting set:
>
> primes100 = {p for p in primes() while p < 100}
>
> At the moment the obvious way to get the prime numbers less than 100
> would be to do something like:
>
> from math import ceil, sqrt
>
> def isprime(N):
> return N > 1 and all(N % n for n in range(2, ceil(sqrt(N))))
>
> primes100 = [p for p in range(1, 100) if isprime(p)]
>
> However this is a suboptimal algorithm. At the point when we want to
> determine if the number N is prime we have already found all the
> primes less than N. We only need to check modulo division against
> those but this construction doesn't give us an easy way to do that.
>
> It's better to have a primes() generator that can keep track of this
> information:
>
> from itertools import count
>
> def primes():
> primes_seen = []
> for n in count(2):
> if all(n % p for p in primes_seen):
> yield n
> primes_seen.append(n)
>
> This algorithm is actually even poorer as it doesn't stop at sqrt(n).
> We can fix that with takewhile:
>
> from itertools import count, takewhile
>
> def primes():
> primes_seen = []
> for n in count(2):
> if all(n % p for p in takewhile(lambda p: p**2 < n, primes_seen)):
> yield n
> primes_seen.append(n)
>
> primes100 = {p for p in takewhile(lambda p: p < 100, primes()}
>
> Using for/while this becomes significantly clearer (in my opinion):
>
> from itertools import count
>
> def primes():
> primes_seen = []
> for n in count(2):
> if all(n % p for p in primes_seen while p**2 <= n):
> yield n
> primes_seen.append(n)
>
> primes100 = {p for p in primes() while p < 100}
>
> The main objection to for/while seems to be that it doesn't unroll in
> the same way as current comprehensions. I think that for/while is just
> as useful for an ordinary for loop as it is for a comprehension. In C
> you can easily add anything to the termination condition for a loop
> e.g.:
>
> for (i=0; i<N && i && p[i-1]<100; ++i)
> p[i] = next_prime();
>
> But in Python having multiple termination conditions (or having any
> termination with an inifinite iterator) means using a break or
> takewhile/lambda.
>
> for n, p in enumerate(primes()):
> if p > 100:
> break
> print('%sth prime is %s' % (n, p))
>
> or perhaps
>
> for n, p in enumerate(takewhile(lambda p: p < 100, primes())):
> print('%sth prime is %s' % (n, p))
>
> or even worse
>
> for n, p in enumerate(takewhile((100).__gt__, primes())):
> print('%sth prime is %s' % (n, p))
>
> I think that it would be better if this could be spelled as
>
> for n, p in enumerate(primes()) while p < 100:
> print('%sth prime is %s' % (n, p))
>
> If that were the case then a for/while comprehension could unroll into
> a for/while loop just as with current comprehensions:
>
> result = [x for y in stuff while z]
>
> becomes:
>
> result = []
> for y in stuff while z:
> result.append(x)
>
>
> Oscar
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20130701/a46a3cbb/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PastedGraphic-1.tiff
Type: image/tiff
Size: 41742 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20130701/a46a3cbb/attachment-0001.tiff>
More information about the Python-ideas
mailing list