[Python-Dev] PEP 3142: Add a "while" clause to generator expressions

Calvin Spealman ironfroggy at gmail.com
Tue Jan 20 01:42:12 CET 2009


OK, I still don't like the general idea, but I have a suggestion for
what I think is a more favorable syntax, anyway. Basically, adding the
allowance of an 'else break' when there is an if clause in a generator
expression or list comprehension. I still dont think it should be
done, but it is a more consistent syntax. It has the obvious problem
of looking like it might allow an alternative expression, like the
if-expression.

prime = (p for p in sieve() if p < 1000 else break)

On Mon, Jan 19, 2009 at 11:47 AM, Calvin Spealman <ironfroggy at gmail.com> wrote:
> On Mon, Jan 19, 2009 at 11:41 AM, Gerald Britton
> <gerald.britton at gmail.com> wrote:
>> Thanks Calvin,
>>
>> Could you please expand on your thoughts about possible confusion?
>> That is, how do you see a programmer becoming confused if this option
>> were added to the syntax.
>
> I think that the difference between these two lines is too easy to
> miss among other code:
>
>    prime = (p for p in sieve() while p < 1000)
>
> and:
>
>    prime = (p for p in sieve() if p < 1000)
>
> The very distinctly different behavior is two important to look so
> similar at a glance. And, again, I just don't see takewhile being used
> all that often. Not nearly often enough to warrant replacing it with a
> special syntax! Only 178 results from Google CodeSearch, while chain,
> groupby, and repeat get 4000, 3000, and 1000 respectively. Should
> those be given their own syntax?
>
>> On Mon, Jan 19, 2009 at 11:29 AM, Calvin Spealman <ironfroggy at gmail.com> wrote:
>>> I am really unconvinced of the utility of this proposal and quite
>>> convinced of the confusing factor it may well add to the current
>>> syntax. I would like to see more applicable examples. It would replace
>>> uses of takewhile, but that isn't a really often used function. So, is
>>> there any evidence to support that making this a new syntax would find
>>> so many more uses of the construct to be worth it? I believe not.
>>>
>>> On Mon, Jan 19, 2009 at 10:10 AM, Gerald Britton
>>> <gerald.britton at gmail.com> wrote:
>>>> Please find below PEP 3142: Add a "while" clause to generator
>>>> expressions.  I'm looking for feedback and discussion.
>>>>
>>>>
>>>> PEP: 3142
>>>> Title: Add a "while" clause to generator expressions
>>>> Version: $Revision: 68715 $
>>>> Last-Modified: $Date: 2009-01-18 11:28:20 +0100 (So, 18. Jan 2009) $
>>>> Author: Gerald Britton <gerald.britton at gmail.com>
>>>> Status: Draft
>>>> Type: Standards Track
>>>> Content-Type: text/plain
>>>> Created: 12-Jan-2009
>>>> Python-Version: 3.0
>>>> Post-History:
>>>>
>>>>
>>>> Abstract
>>>>
>>>>  This PEP proposes an enhancement to generator expressions, adding a
>>>>  "while" clause to complement the existing "if" clause.
>>>>
>>>>
>>>> Rationale
>>>>
>>>>  A generator expression (PEP 289 [1]) is a concise method to serve
>>>>  dynamically-generated objects to list comprehensions (PEP 202 [2]).
>>>>  Current generator expressions allow for an "if" clause to filter
>>>>  the objects that are returned to those meeting some set of
>>>>  criteria.  However, since the "if" clause is evaluated for every
>>>>  object that may be returned, in some cases it is possible that all
>>>>  objects would be rejected after a certain point.  For example:
>>>>
>>>>      g = (n for n in range(100) if n*n < 50)
>>>>
>>>>  which is equivalent to the using a generator function
>>>>  (PEP 255 [3]):
>>>>
>>>>      def __gen(exp):
>>>>          for n in exp:
>>>>              if n*n < 50:
>>>>                  yield n
>>>>      g = __gen(iter(range(10)))
>>>>
>>>>  would yield 0, 1, 2, 3, 4, 5, 6 and 7, but would also consider
>>>>  the numbers from 8 to 99 and reject them all since n*n >= 50 for
>>>>  numbers in that range.  Allowing for a "while" clause would allow
>>>>  the redundant tests to be short-circuited:
>>>>
>>>>      g = (n for n in range(100) while n*n < 50)
>>>>
>>>>  would also yield 0, 1, 2, 3, 4, 5, 6 and 7, but would stop at 8
>>>>  since the condition (n*n < 50) is no longer true.  This would be
>>>>  equivalent to the generator function:
>>>>
>>>>      def __gen(exp):
>>>>          for n in exp:
>>>>              if n*n < 50:
>>>>                  yield n
>>>>              else:
>>>>                  break
>>>>      g = __gen(iter(range(100)))
>>>>
>>>>  Currently, in order to achieve the same result, one would need to
>>>>  either write a generator function such as the one above or use the
>>>>  takewhile function from itertools:
>>>>
>>>>      from itertools import takewhile
>>>>      g = takewhile(lambda n: n*n < 50, range(100))
>>>>
>>>>  The takewhile code achieves the same result as the proposed syntax,
>>>>  albeit in a longer (some would say "less-elegant") fashion.  Also,
>>>>  the takewhile version requires an extra function call (the lambda
>>>>  in the example above) with the associated performance penalty.
>>>>  A simple test shows that:
>>>>
>>>>      for n in (n for n in range(100) if 1): pass
>>>>
>>>>  performs about 10% better than:
>>>>
>>>>      for n in takewhile(lambda n: 1, range(100)): pass
>>>>
>>>>  though they achieve similar results.  (The first example uses a
>>>>  generator; takewhile is an iterator).  If similarly implemented,
>>>>  a "while" clause should perform about the same as the "if" clause
>>>>  does today.
>>>>
>>>>  The reader may ask if the "if" and "while" clauses should be
>>>>  mutually exclusive.  There are good examples that show that there
>>>>  are times when both may be used to good advantage. For example:
>>>>
>>>>      p = (p for p in primes() if p > 100 while p < 1000)
>>>>
>>>>  should return prime numbers found between 100 and 1000, assuming
>>>>  I have a primes() generator that yields prime numbers.  Of course, this
>>>>  could also be achieved like this:
>>>>
>>>>      p = (p for p in (p for p in primes() if p > 100) while p < 1000)
>>>>
>>>>  which is syntactically simpler.  Some may also ask if it is possible
>>>>  to cover dropwhile() functionality in a similar way.  I initially thought
>>>>  of:
>>>>
>>>>      p = (p for p in primes() not while p < 100)
>>>>
>>>>  but I am not sure that I like it since it uses "not" in a non-pythonic
>>>>  fashion, I think.
>>>>
>>>>  Adding a "while" clause to generator expressions maintains the
>>>>  compact form while adding a useful facility for short-circuiting
>>>>  the expression.
>>>>
>>>> Implementation:
>>>>
>>>>  I am willing to assist in the implementation of this feature, although I have
>>>>  not contributed to Python thus far and would definitely need mentoring. (At
>>>>  this point I am not quite sure where to begin.)  Presently though, I would
>>>>  find it challenging to fit this work into my existing workload.
>>>>
>>>>
>>>> Acknowledgements
>>>>
>>>>  Raymond Hettinger first proposed the concept of generator
>>>>  expressions in January 2002.
>>>>
>>>>
>>>> References
>>>>
>>>>  [1] PEP 289: Generator Expressions
>>>>      http://www.python.org/dev/peps/pep-0289/
>>>>
>>>>  [2] PEP 202: List Comprehensions
>>>>      http://www.python.org/dev/peps/pep-0202/
>>>>
>>>>  [3] PEP 255: Simple Generators
>>>>      http://www.python.org/dev/peps/pep-0255/
>>>>
>>>>
>>>> Copyright
>>>>
>>>>  This document has been placed in the public domain.
>>>>
>>>>
>>>> Local Variables:
>>>> mode: indented-text
>>>> indent-tabs-mode: nil
>>>> sentence-end-double-space: t
>>>> fill-column: 70
>>>> coding: utf-8
>>>> End:
>>>>
>>>> _______________________________________________
>>>> Python-Dev mailing list
>>>> Python-Dev at python.org
>>>> http://mail.python.org/mailman/listinfo/python-dev
>>>> Unsubscribe: http://mail.python.org/mailman/options/python-dev/ironfroggy%40gmail.com
>>>>
>>>>
>>>
>>>
>>>
>>> --
>>> Read my blog! I depend on your acceptance of my opinion! I am interesting!
>>> http://techblog.ironfroggy.com/
>>> Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy
>>>
>>
>
>
>
> --
> Read my blog! I depend on your acceptance of my opinion! I am interesting!
> http://techblog.ironfroggy.com/
> Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy
>



-- 
Read my blog! I depend on your acceptance of my opinion! I am interesting!
http://techblog.ironfroggy.com/
Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy


More information about the Python-Dev mailing list