Doc note cross-referencing PEP 798 from itertools.chain / chain.from_iterable
Now that PEP 798 (Unpacking in Comprehensions) is accepted and slated for 3.15, I’d like to propose a small, docs-only addition: a short note in the itertools.chain and itertools.chain.from_iterable entries pointing readers to the new unpacking-in-comprehension syntax as an inline alternative for flattening.
Why
chain.from_iterable is effectively the textbook motivating example for PEP 798 — the PEP’s own “Replacing from_iterable and Friends” section rewrites several stdlib call sites in terms of (*it for it in its). Readers who land on the itertools docs reaching for from_iterable to flatten an iterable of iterables are exactly the audience who’d benefit from knowing the inline form now exists, but nothing in the itertools docs currently signals it.
This is purely a discoverability nudge, not a redirect.
What I’m not proposing
- No change to the “roughly equivalent” code. The reference equivalent uses
yield from, and I think it should stay classic and version-agnostic. (Tangentially: the genexp form’s explicit-loop semantics — no.send()/.throw()/.close()delegation — actually model the C object slightly more faithfully thanyield fromdoes, but that’s far too subtle to belong in the reference snippet.) - No deprecation, no recommendation.
chain/from_iterableremain the right tool as first-class callables (e.g.map(chain.from_iterable, ...)), in code targeting < 3.15, and in hot paths where the C implementation wins. The PEP explicitly notes that replacingfrom_iterableis “not always the right choice,” so the note should read as a pointer, not advice.
Proposed wording (rough — bikeshed welcome)
For chain.from_iterable (the primary target):
Note: Since Python 3.15, a list, set, or generator can be built inline from an arbitrary number of iterables using unpacking in a comprehension or generator expression (see PEP 798), for example
(*it for it in iterables)or[*it for it in iterables]. This is often more readable for simple flattening;chain.from_iterableremains useful as a first-class callable and in code targeting earlier versions.
For chain, I’d keep it lighter, because the fixed-arity case chain(a, b, c) already has a PEP 448 inline form [*a, *b, *c]. The PEP 798 form is the natural inline alternative specifically when one would otherwise write chain(*iterables) over an arbitrary sequence — so a one-line cross-reference to the from_iterable note (or to PEP 798) is probably enough rather than a duplicate block.
Open questions for discussion
- Is a
See also/Notewanted here at all, or is this the kind of “every function could point at newer syntax” creep the docs try to avoid? - Touch only
from_iterable, or both entries? - Phrasing of the version marker — a
.. versionchanged:: 3.15feels wrong (the function didn’t change), so probably just an inline “Since 3.15” in the note text.
Happy to put up a docs PR if there’s appetite. Mostly want to gauge interest and settle scope/wording first.