fixed list indentation; status: Draft is correct

This commit is contained in:
David Goodger 2003-10-23 12:51:30 +00:00
parent 59156b6c63
commit 326a56a0f3
1 changed files with 86 additions and 84 deletions

View File

@ -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.