[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