fixed list indentation; status: Draft is correct
This commit is contained in:
parent
59156b6c63
commit
326a56a0f3
170
pep-0289.txt
170
pep-0289.txt
|
@ -3,7 +3,7 @@ Title: Generator Expressions
|
||||||
Version: $Revision$
|
Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: python@rcn.com (Raymond D. Hettinger)
|
Author: python@rcn.com (Raymond D. Hettinger)
|
||||||
Status: Active
|
Status: Draft
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
Content-Type: text/x-rst
|
Content-Type: text/x-rst
|
||||||
Created: 30-Jan-2002
|
Created: 30-Jan-2002
|
||||||
|
@ -91,122 +91,124 @@ c.l.py. The Python Reference Manual should contain a 100% exact
|
||||||
semantic and syntactic specification.)
|
semantic and syntactic specification.)
|
||||||
|
|
||||||
1. The semantics of a generator expression are equivalent to creating
|
1. The semantics of a generator expression are equivalent to creating
|
||||||
an anonymous generator function and calling it. For example::
|
an anonymous generator function and calling it. For example::
|
||||||
|
|
||||||
g = (x**2 for x in range(10))
|
g = (x**2 for x in range(10))
|
||||||
print g.next()
|
print g.next()
|
||||||
|
|
||||||
is equivalent to::
|
is equivalent to::
|
||||||
|
|
||||||
def __gen():
|
def __gen():
|
||||||
for x in range(10):
|
for x in range(10):
|
||||||
yield x**2
|
yield x**2
|
||||||
g = __gen()
|
g = __gen()
|
||||||
print g.next()
|
print g.next()
|
||||||
|
|
||||||
2. The syntax requires that a generator expression always needs to be
|
2. The syntax requires that a generator expression always needs to be
|
||||||
directly inside a set of parentheses and cannot have a comma on either
|
directly inside a set of parentheses and cannot have a comma on
|
||||||
side. With reference to the file Grammar/Grammar in CVS, two rules
|
either side. With reference to the file Grammar/Grammar in CVS,
|
||||||
change:
|
two rules change:
|
||||||
|
|
||||||
a) The rule::
|
a) The rule::
|
||||||
|
|
||||||
atom: '(' [testlist] ')'
|
atom: '(' [testlist] ')'
|
||||||
|
|
||||||
changes to::
|
changes to::
|
||||||
|
|
||||||
atom: '(' [listmaker1] ')'
|
atom: '(' [listmaker1] ')'
|
||||||
|
|
||||||
where listmaker1 is almost the same as listmaker, but only allows
|
where listmaker1 is almost the same as listmaker, but only
|
||||||
a single test after 'for' ... 'in'.
|
allows a single test after 'for' ... 'in'.
|
||||||
|
|
||||||
b) The rule for arglist needs similar changes.
|
b) The rule for arglist needs similar changes.
|
||||||
|
|
||||||
This means that you can write::
|
This means that you can write::
|
||||||
|
|
||||||
sum(x**2 for x in range(10))
|
sum(x**2 for x in range(10))
|
||||||
|
|
||||||
but you would have to write::
|
but you would have to write::
|
||||||
|
|
||||||
reduce(operator.add, (x**2 for x in range(10)))
|
reduce(operator.add, (x**2 for x in range(10)))
|
||||||
|
|
||||||
and also::
|
and also::
|
||||||
|
|
||||||
g = (x**2 for i in range(10))
|
g = (x**2 for i in range(10))
|
||||||
|
|
||||||
i.e. if a function call has a single positional argument, it can be a
|
i.e. if a function call has a single positional argument, it can be
|
||||||
generator expression without extra parentheses, but in all other cases
|
a generator expression without extra parentheses, but in all other
|
||||||
you have to parenthesize it.
|
cases you have to parenthesize it.
|
||||||
|
|
||||||
3. The loop variable (if it is a simple variable or a tuple of simple
|
3. The loop variable (if it is a simple variable or a tuple of simple
|
||||||
variables) is not exposed to the surrounding function. This facilates
|
variables) is not exposed to the surrounding function. This
|
||||||
the implementation and makes typical use cases more reliable. In some
|
facilates the implementation and makes typical use cases more
|
||||||
future version of Python, list comprehensions will also hide the
|
reliable. In some future version of Python, list comprehensions
|
||||||
induction variable from the surrounding code (and, in Py2.4, warnings
|
will also hide the induction variable from the surrounding code
|
||||||
will be issued for code accessing the induction variable).
|
(and, in Py2.4, warnings will be issued for code accessing the
|
||||||
|
induction variable).
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
x = "hello"
|
x = "hello"
|
||||||
y = list(x for x in "abc")
|
y = list(x for x in "abc")
|
||||||
print x # prints "hello", not "c"
|
print x # prints "hello", not "c"
|
||||||
|
|
||||||
(Loop variables may also use constructs like x[i] or x.a; this form
|
(Loop variables may also use constructs like x[i] or x.a; this form
|
||||||
may be deprecated.)
|
may be deprecated.)
|
||||||
|
|
||||||
4. All free variable bindings are captured at the time this function
|
4. All free variable bindings are captured at the time this function
|
||||||
is defined, and passed into it using default argument values. For
|
is defined, and passed into it using default argument values. For
|
||||||
example::
|
example::
|
||||||
|
|
||||||
x = 0
|
x = 0
|
||||||
g = (x for c in "abc") # x is not the loop variable!
|
g = (x for c in "abc") # x is not the loop variable!
|
||||||
x = 1
|
x = 1
|
||||||
print g.next() # prints 0 (captured x), not 1 (current x)
|
print g.next() # prints 0 (captured x), not 1 (current x)
|
||||||
|
|
||||||
This behavior of free variables is almost always what you want when
|
This behavior of free variables is almost always what you want when
|
||||||
the generator expression is evaluated at a later point than its
|
the generator expression is evaluated at a later point than its
|
||||||
definition. In fact, to date, no examples have been found of code
|
definition. In fact, to date, no examples have been found of code
|
||||||
where it would be better to use the execution-time instead of the
|
where it would be better to use the execution-time instead of the
|
||||||
definition-time value of a free variable.
|
definition-time value of a free variable.
|
||||||
|
|
||||||
Note that free variables aren't copied, only their binding is
|
Note that free variables aren't copied, only their binding is
|
||||||
captured. They may still change if they are mutable, for example::
|
captured. They may still change if they are mutable, for example::
|
||||||
|
|
||||||
x = []
|
x = []
|
||||||
g = (x for c in "abc")
|
g = (x for c in "abc")
|
||||||
x.append(1)
|
x.append(1)
|
||||||
print g.next() # prints [1], not []
|
print g.next() # prints [1], not []
|
||||||
|
|
||||||
5. List comprehensions will remain unchanged. For example::
|
5. List comprehensions will remain unchanged. For example::
|
||||||
|
|
||||||
[x for x in S] # This is a list comprehension.
|
[x for x in S] # This is a list comprehension.
|
||||||
[(x for x in S)] # This is a list containing one generator expression.
|
[(x for x in S)] # This is a list containing one generator
|
||||||
|
# expression.
|
||||||
|
|
||||||
Unfortunately, there is currently a slight syntactic difference. The
|
Unfortunately, there is currently a slight syntactic difference.
|
||||||
expression::
|
The expression::
|
||||||
|
|
||||||
[x for x in 1, 2, 3]
|
[x for x in 1, 2, 3]
|
||||||
|
|
||||||
is legal, meaning::
|
is legal, meaning::
|
||||||
|
|
||||||
[x for x in (1, 2, 3)]
|
[x for x in (1, 2, 3)]
|
||||||
|
|
||||||
But generator expressions will not allow the former version::
|
But generator expressions will not allow the former version::
|
||||||
|
|
||||||
(x for x in 1, 2, 3)
|
(x for x in 1, 2, 3)
|
||||||
|
|
||||||
is illegal.
|
is illegal.
|
||||||
|
|
||||||
The former list comprehension syntax will become illegal in Python
|
The former list comprehension syntax will become illegal in Python
|
||||||
3.0, and should be deprecated in Python 2.4 and beyond.
|
3.0, and should be deprecated in Python 2.4 and beyond.
|
||||||
|
|
||||||
List comprehensions also "leak" their loop variable into the
|
List comprehensions also "leak" their loop variable into the
|
||||||
surrounding scope. This will also change in Python 3.0, so that the
|
surrounding scope. This will also change in Python 3.0, so that
|
||||||
semantic definition of a list comprehension in Python 3.0 will be
|
the semantic definition of a list comprehension in Python 3.0 will
|
||||||
equivalent to list(<generator expression>). Python 2.4 and beyond
|
be equivalent to list(<generator expression>). Python 2.4 and
|
||||||
should issue a deprecation warning if a list comprehension's loop
|
beyond should issue a deprecation warning if a list comprehension's
|
||||||
variable has the same name as a variable used in the immediately
|
loop variable has the same name as a variable used in the
|
||||||
surrounding scope.
|
immediately surrounding scope.
|
||||||
|
|
||||||
|
|
||||||
Reduction Functions
|
Reduction Functions
|
||||||
|
@ -215,25 +217,25 @@ Reduction Functions
|
||||||
The utility of generator expressions is greatly enhanced when combined
|
The utility of generator expressions is greatly enhanced when combined
|
||||||
with reduction functions like sum(), min(), and max(). Separate
|
with reduction functions like sum(), min(), and max(). Separate
|
||||||
proposals are forthcoming that recommend several new accumulation
|
proposals are forthcoming that recommend several new accumulation
|
||||||
functions possibly including: product(), average(), alltrue(),
|
functions possibly including: product(), average(), alltrue(),
|
||||||
anytrue(), nlargest(), nsmallest().
|
anytrue(), nlargest(), nsmallest().
|
||||||
|
|
||||||
|
|
||||||
Acknowledgements
|
Acknowledgements
|
||||||
================
|
================
|
||||||
|
|
||||||
* Raymond Hettinger first proposed the idea of "generator comprehensions"
|
* Raymond Hettinger first proposed the idea of "generator
|
||||||
in January 2002.
|
comprehensions" in January 2002.
|
||||||
|
|
||||||
* Peter Norvig resurrected the discussion in his proposal for
|
* Peter Norvig resurrected the discussion in his proposal for
|
||||||
Accumulation Displays.
|
Accumulation Displays.
|
||||||
|
|
||||||
* Alex Martelli provided critical measurements that proved the performance
|
* Alex Martelli provided critical measurements that proved the
|
||||||
benefits of generator expressions. He also provided strong arguments
|
performance benefits of generator expressions. He also provided
|
||||||
that they were a desirable thing to have.
|
strong arguments that they were a desirable thing to have.
|
||||||
|
|
||||||
* Samuele Pedroni provided the example of late binding.
|
* Samuele Pedroni provided the example of late binding. Various
|
||||||
Various contributors have made arguments for and against late binding.
|
contributors have made arguments for and against late binding.
|
||||||
|
|
||||||
* Phillip Eby suggested "iterator expressions" as the name.
|
* Phillip Eby suggested "iterator expressions" as the name.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue