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

Calvin Spealman ironfroggy at gmail.com
Mon Jan 19 17:29:28 CET 2009


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


More information about the Python-Dev mailing list