Skip to content

Commit a565b86

Browse files
StanFromIrelandencukoublaisep
authored
[3.14] gh-141984: Reword the Generator expressions section (GH-150518) (GH-151267)
(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 8cefa57 commit a565b86

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
@@ -550,39 +550,100 @@ Generator expressions
550550
pair: object; generator
551551
single: () (parentheses); generator expression
552552

553-
A generator expression is a compact generator notation in parentheses:
553+
The syntax for :dfn:`generator expressions` is the same as for
554+
list :ref:`comprehensions <comprehensions>`, except that they are enclosed in
555+
parentheses instead of brackets.
556+
For example::
554557

555-
.. productionlist:: python-grammar
556-
generator_expression: "(" `expression` `comp_for` ")"
558+
>>> iterator = (x ** 2 for x in range(10))
559+
>>> iterator
560+
<generator object <genexpr> at ...>
561+
562+
At runtime, a generator expression evaluates to a :term:`generator iterator`
563+
which yields the same values as the corresponding list comprehension::
564+
565+
>>> list(iterator)
566+
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
567+
568+
Thus, the example above is roughly equivalent to defining and calling
569+
the following generator function::
570+
571+
def make_generator_of_squares(iterator):
572+
for x in iterator:
573+
yield x ** 2
574+
575+
make_generator_of_squares(iter(range(10)))
576+
577+
The enclosing parentheses can be omitted in calls when the generator
578+
expression is the only positional argument and there are no keyword
579+
arguments.
580+
See the :ref:`Calls section <calls>` for details.
581+
For example::
582+
583+
# The parentheses after `sum` are part of the call syntax:
584+
>>> sum(x ** 2 for x in range(10))
585+
285
586+
587+
# The generator needs its own parentheses if it's not the only argument:
588+
>>> sum((x ** 2 for x in range(10)), start=1000)
589+
1285
590+
591+
The iterable expression in the leftmost :keyword:`!for` clause is
592+
evaluated immediately, so that an error raised by this expression will be
593+
emitted at the point where the generator expression is defined,
594+
rather than at the point where the first value is retrieved::
595+
596+
>>> (x ** 2 for x in nonexistent_iterable)
597+
Traceback (most recent call last):
598+
...
599+
NameError: name 'nonexistent_iterable' is not defined
557600

558-
A generator expression yields a new generator object. Its syntax is the same as
559-
for comprehensions, except that it is enclosed in parentheses instead of
560-
brackets or curly braces.
561-
562-
Variables used in the generator expression are evaluated lazily when the
563-
:meth:`~generator.__next__` method is called for the generator object (in the same
564-
fashion as normal generators). However, the iterable expression in the
565-
leftmost :keyword:`!for` clause is immediately evaluated, and the
566-
:term:`iterator` is immediately created for that iterable, so that an error
567-
produced while creating the iterator will be emitted at the point where the generator expression
568-
is defined, rather than at the point where the first value is retrieved.
569-
Subsequent :keyword:`!for` clauses and any filter condition in the leftmost
570-
:keyword:`!for` clause cannot be evaluated in the enclosing scope as they may
571-
depend on the values obtained from the leftmost iterable. For example:
572-
``(x*y for x in range(10) for y in range(x, x+10))``.
573-
574-
The parentheses can be omitted on calls with only one argument. See section
575-
:ref:`calls` for details.
601+
After the expression is evaluated, an iterator is created
602+
from the result, as if :py:func:`iter` was called on it.
603+
Any error raised when creating the iterator is also emitted immediately::
604+
605+
>>> (x ** 2 for x in None)
606+
Traceback (most recent call last):
607+
...
608+
TypeError: 'NoneType' object is not iterable
609+
610+
All other expressions are evaluated lazily, in the same fashion as normal
611+
generators (that is, when the iterator is asked to yield a value)::
612+
613+
>>> iterator = (nonexistent_value for x in range(10))
614+
>>> iterator
615+
<generator object <genexpr> at ...>
616+
>>> list(iterator)
617+
Traceback (most recent call last):
618+
...
619+
NameError: name 'nonexistent_value' is not defined
620+
621+
::
622+
623+
>>> iterator = (x * y for x in range(10) for y in nonexistent_iterable)
624+
>>> iterator
625+
<generator object <genexpr> at ...>
626+
>>> list(iterator)
627+
Traceback (most recent call last):
628+
...
629+
NameError: name 'nonexistent_iterable' is not defined
576630

577631
To avoid interfering with the expected operation of the generator expression
578-
itself, ``yield`` and ``yield from`` expressions are prohibited in the
579-
implicitly defined generator.
632+
itself, ``yield`` and ``yield from`` expressions are prohibited inside
633+
the implicitly nested scope.
580634

581635
If a generator expression contains either :keyword:`!async for`
582636
clauses or :keyword:`await` expressions it is called an
583-
:dfn:`asynchronous generator expression`. An asynchronous generator
584-
expression returns a new asynchronous generator object,
585-
which is an asynchronous iterator (see :ref:`async-iterators`).
637+
:dfn:`asynchronous generator expression`.
638+
An asynchronous generator expression returns a new asynchronous generator
639+
object, which is an asynchronous iterator (see :ref:`async-iterators`).
640+
641+
The formal grammar for generator expressions is:
642+
643+
.. grammar-snippet::
644+
:group: python-grammar
645+
646+
generator_expression: "(" `expression` `comp_for` ")"
586647

587648
.. versionadded:: 3.6
588649
Asynchronous generator expressions were introduced.

0 commit comments

Comments
 (0)