Skip to content

Commit f76c352

Browse files
encukoublaisepStanFromIreland
authored andcommitted
gh-141984: Reword the Generator expressions section (GH-150518)
(cherry picked from commit 7bbb960) Co-authored-by: Petr Viktorin <encukou@gmail.com> Co-authored-by: Blaise Pabon <blaise@gmail.com> Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent 9261f8b commit f76c352

1 file changed

Lines changed: 87 additions & 26 deletions

File tree

Doc/reference/expressions.rst

Lines changed: 87 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -956,39 +956,100 @@ Generator expressions
956956
pair: object; generator
957957
single: () (parentheses); generator expression
958958

959-
A generator expression is a compact generator notation in parentheses:
959+
The syntax for :dfn:`generator expressions` is the same as for
960+
list :ref:`comprehensions <comprehensions>`, except that they are enclosed in
961+
parentheses instead of brackets.
962+
For example::
960963

961-
.. productionlist:: python-grammar
962-
generator_expression: "(" `comprehension` ")"
964+
>>> iterator = (x ** 2 for x in range(10))
965+
>>> iterator
966+
<generator object <genexpr> at ...>
967+
968+
At runtime, a generator expression evaluates to a :term:`generator iterator`
969+
which yields the same values as the corresponding list comprehension::
970+
971+
>>> list(iterator)
972+
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
973+
974+
Thus, the example above is roughly equivalent to defining and calling
975+
the following generator function::
963976

964-
A generator expression yields a new generator object. Its syntax is the same as
965-
for comprehensions, except that it is enclosed in parentheses instead of
966-
brackets or curly braces.
967-
968-
Variables used in the generator expression are evaluated lazily when the
969-
:meth:`~generator.__next__` method is called for the generator object (in the same
970-
fashion as normal generators). However, the iterable expression in the
971-
leftmost :keyword:`!for` clause is immediately evaluated, and the
972-
:term:`iterator` is immediately created for that iterable, so that an error
973-
produced while creating the iterator will be emitted at the point where the generator expression
974-
is defined, rather than at the point where the first value is retrieved.
975-
Subsequent :keyword:`!for` clauses and any filter condition in the leftmost
976-
:keyword:`!for` clause cannot be evaluated in the enclosing scope as they may
977-
depend on the values obtained from the leftmost iterable. For example:
978-
``(x*y for x in range(10) for y in range(x, x+10))``.
979-
980-
The parentheses can be omitted on calls with only one argument. See section
981-
:ref:`calls` for details.
977+
def make_generator_of_squares(iterator):
978+
for x in iterator:
979+
yield x ** 2
980+
981+
make_generator_of_squares(iter(range(10)))
982+
983+
The enclosing parentheses can be omitted in calls when the generator
984+
expression is the only positional argument and there are no keyword
985+
arguments.
986+
See the :ref:`Calls section <calls>` for details.
987+
For example::
988+
989+
# The parentheses after `sum` are part of the call syntax:
990+
>>> sum(x ** 2 for x in range(10))
991+
285
992+
993+
# The generator needs its own parentheses if it's not the only argument:
994+
>>> sum((x ** 2 for x in range(10)), start=1000)
995+
1285
996+
997+
The iterable expression in the leftmost :keyword:`!for` clause is
998+
evaluated immediately, so that an error raised by this expression will be
999+
emitted at the point where the generator expression is defined,
1000+
rather than at the point where the first value is retrieved::
1001+
1002+
>>> (x ** 2 for x in nonexistent_iterable)
1003+
Traceback (most recent call last):
1004+
...
1005+
NameError: name 'nonexistent_iterable' is not defined
1006+
1007+
After the expression is evaluated, an iterator is created
1008+
from the result, as if :py:func:`iter` was called on it.
1009+
Any error raised when creating the iterator is also emitted immediately::
1010+
1011+
>>> (x ** 2 for x in None)
1012+
Traceback (most recent call last):
1013+
...
1014+
TypeError: 'NoneType' object is not iterable
1015+
1016+
All other expressions are evaluated lazily, in the same fashion as normal
1017+
generators (that is, when the iterator is asked to yield a value)::
1018+
1019+
>>> iterator = (nonexistent_value for x in range(10))
1020+
>>> iterator
1021+
<generator object <genexpr> at ...>
1022+
>>> list(iterator)
1023+
Traceback (most recent call last):
1024+
...
1025+
NameError: name 'nonexistent_value' is not defined
1026+
1027+
::
1028+
1029+
>>> iterator = (x * y for x in range(10) for y in nonexistent_iterable)
1030+
>>> iterator
1031+
<generator object <genexpr> at ...>
1032+
>>> list(iterator)
1033+
Traceback (most recent call last):
1034+
...
1035+
NameError: name 'nonexistent_iterable' is not defined
9821036

9831037
To avoid interfering with the expected operation of the generator expression
984-
itself, ``yield`` and ``yield from`` expressions are prohibited in the
985-
implicitly defined generator.
1038+
itself, ``yield`` and ``yield from`` expressions are prohibited inside
1039+
the implicitly nested scope.
9861040

9871041
If a generator expression contains either :keyword:`!async for`
9881042
clauses or :keyword:`await` expressions it is called an
989-
:dfn:`asynchronous generator expression`. An asynchronous generator
990-
expression returns a new asynchronous generator object,
991-
which is an asynchronous iterator (see :ref:`async-iterators`).
1043+
:dfn:`asynchronous generator expression`.
1044+
An asynchronous generator expression returns a new asynchronous generator
1045+
object, which is an asynchronous iterator (see :ref:`async-iterators`).
1046+
1047+
The formal grammar for generator expressions is:
1048+
1049+
.. grammar-snippet::
1050+
:group: python-grammar
1051+
1052+
generator_expression: "(" `comprehension` ")"
9921053

9931054
.. versionadded:: 3.6
9941055
Asynchronous generator expressions were introduced.

0 commit comments

Comments
 (0)