@@ -217,26 +217,33 @@ Semantics: Generator Expressions
217217Generator expressions using the unpacking syntax should form new generators
218218producing values from the concatenation of the iterables given by the
219219expressions. Specifically, the behavior is defined to be equivalent to the
220- following (though without defining or referencing the looping variable
221- ``i ``)::
220+ following::
222221
223- # equivalent to generator = (*expr for x in it)
222+ # equivalent to g = (*expr for x in it)
224223 def generator():
225224 for x in it:
226- for i in expr:
227- yield i
225+ yield from expr
226+
227+ g = generator()
228+
229+ Since ``yield from `` is not allowed inside of async generators (see the section
230+ of :pep: `525 ` on Asynchronous ``yield from ``), the equivalent for ``(*expr
231+ async for x in ait()) `` is more like the following (though of course this new
232+ form should not define or reference the looping variable ``i ``)::
228233
229- # equivalent to generator = (*expr async for x in ait())
234+ # equivalent to g = (*expr async for x in ait())
230235 async def generator():
231236 async for x in ait():
232237 for i in expr:
233238 yield i
234239
240+ g = generator()
241+
235242The specifics of these semantics should be revisited in the future,
236243particularly if async generators receive support for ``yield from `` (in which
237- case both forms may wish to be changed to make use of ``yield from `` instead of
238- an explicit loop). See :ref: `pep798-alternativegenexpsemantics ` for more
239- discussion.
244+ case the async variant may wish to be changed to make use of ``yield from ``
245+ instead of an explicit loop). See :ref: `pep798-alternativegenexpsemantics ` for
246+ more discussion.
240247
241248Interaction with Assignment Expressions
242249^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -255,8 +262,7 @@ form, ``y`` will be bound in the containing scope instead of locally::
255262
256263 def generator():
257264 for i in (0, 2, 4):
258- for j in (y := [i, i+1]):
259- yield j
265+ yield from (y := [i, i+1])
260266
261267In this example, the subexpression ``(y := [i, i+1]) `` is evaluated exactly
262268three times before the generator is exhausted: just after assigning ``i `` in
@@ -390,11 +396,11 @@ in comprehensions would raise a ``SyntaxError``, or that relied on the
390396particular phrasing of any of the old error messages being replaced, which we
391397expect to be rare.
392398
393- One related concern is that a hypotehtical future decision to change the
394- semantics of generator expressions to make use of ``yield from `` during
399+ One related concern is that a hypothetical future decision to change the
400+ semantics of async generator expressions to make use of ``yield from `` during
395401unpacking (delegating to generators that are being unpacked) would be not be
396402backwards-compatible because it would affect the behavior of the resulting
397- generators when used with ``.send () ``, ``.throw () ``, and ``.close () ``. See
403+ generators when used with ``.asend () ``, ``.athrow () ``, and ``.aclose () ``. See
398404:ref: `pep798-alternativegenexpsemantics ` for more discussion.
399405
400406.. _pep798-examples :
@@ -730,37 +736,38 @@ synchronous and asynchronous generator expressions given that async generators
730736do not support ``yield from `` (see the section of :pep: `525 ` on Asynchronous
731737``yield from ``).
732738
733- The core question centered around whether sync and/or async generator
734- expressions should use ``yield from `` (or an equivalent) when unpacking, as
735- opposed to an explicit loop. The main difference between these options is
736- whether the resulting generator delegates to the objects being unpacked (see
737- :pep: ` 380 `), which would affect the behavior of these generator expressions
738- when used with ``.send() ``, ``.throw() ``, and ``.close() ``, in the case where
739- the objects being unpacked are themselves generators, which appears to be a
740- rare situation .
739+ The core question centered around whether sync and async generator expressions
740+ should use ``yield from `` (or an equivalent) when unpacking, as opposed to an
741+ explicit loop. The main difference between these options is whether the
742+ resulting generator delegates to the objects being unpacked (see :pep: ` 380 `),
743+ which would affect the behavior of these generator expressions when used with
744+ ``.send()/.asend() ``, ``.throw()/.athrow() ``, and ``.close()/.aclose() ``, in
745+ the case where the objects being unpacked are themselves generators, which
746+ is unlikely to be a common use case .
741747
742748Several reasonable options were considered, none of which was a clear winner in
743749a `poll in the Discourse thread
744- <https://discuss.python.org/t/pep-798-unpacking-in-comprehensions/99435/33> `__:
750+ <https://discuss.python.org/t/pep-798-unpacking-in-comprehensions/99435/33> `__.
751+ Beyond the proposal outlined above, the following were also considered:
745752
746- 1. Using ``yield from `` for unpacking in synchronous generator expressions but
747- not in asynchronous generator expressions (as proposed in the original draft
748- of this PEP).
753+ 1. Using explicit loops for both synchronous and asynchronous generator
754+ expressions.
749755
750- This strategy would have allowed unpacking in generator expressions to
751- closely mimic a popular way of writing generators that perform this
752- operation (using ``yield from ``), but it would also have created an
753- asymmetry between synchronous and asynchronous versions, and also between
754- this new syntax and ``itertools.chain `` and the double-loop version.
756+ This strategy would have resulted in a symmetry between synchronous and
757+ asynchronous generator expressions but would have prevented a
758+ potentially-useful tool by disallowing delegation in the case of synchronous
759+ generator expressions. Moreover, the existing asymmetry between synchronous
760+ and asynchronous generators mitigates concerns about asymmetry of the
761+ unpacking operator within generator expressions.
755762
7567632. Using ``yield from `` for unpacking in synchronous generator expressions and
757764 mimicking the behavior of ``yield from `` for unpacking in async generator
758765 expressions.
759766
760767 This strategy would also make unpacking in synchronous and asynchronous
761- generators behave similarly , but it would also be more complex, enough so
762- that the cost may not be worth the benefit, particularly in the absence of a
763- compelling practical use case for delegating to subgenerators during
768+ generators behave symmetrically , but it would also be more complex, enough
769+ so that the cost may not be worth the benefit, particularly in the absence
770+ of a compelling practical use case for delegating to subgenerators during
764771 unpacking.
765772
7667733. Using ``yield from `` for unpacking in synchronous generator expressions, and
@@ -770,25 +777,26 @@ a `poll in the Discourse thread
770777 This strategy could possibly reduce friction if asynchronous generator
771778 expressions do gain support for ``yield from `` in the future by making sure
772779 that any decision made at that point would be fully backwards-compatible,
773- but in the meantime, it would result in an even bigger discrepancy between
774- synchronous and asynchronous generator expressions than option 1.
780+ but the utility of unpacking in that context seems to outweigh the potential
781+ downside of a backwards-incompatible change in the future if aync generator
782+ expressions do receive support for ``yield from ``.
775783
7767844. Disallowing unpacking in all generator expressions.
777785
778786 This would retain symmetry between the two cases, but with the downside of
779787 losing a very expressive form.
780788
789+
781790Each of these options (including the one presented in this PEP) has its
782791benefits and drawbacks, with no option being clearly superior on all fronts;
783792but the semantics proposed in :ref: `pep798-genexpsemantics ` represent a
784- reasonable compromise by allowing exactly the same kind of unpacking in
785- synchronous and asynchronous generator expressions and retaining an existing
786- property of generator expressions (that they do not
787-
788- As suggested above, this decision should be revisited in the event that
789- asynchronous generators receive support for ``yield from `` in the future,
790- in which case the ability to delegate to subgenerators during unpacking
791- could be added without significant cost.
793+ reasonable compromise where unpacking in both synchronous and asynchronous
794+ generator expressions mirrors common ways of writing equivalent generators.
795+
796+ As suggested above, though, this decision should be revisited in the event that
797+ asynchronous generators receive support for ``yield from `` in the future, in
798+ which case adjusting the semantics of unpacking in async generator expressions
799+ to use ``yield from `` should be considered.
792800
793801
794802Concerns and Disadvantages
0 commit comments