Skip to content

Commit 30228c5

Browse files
encukoublaisepStanFromIreland
committed
Work on comprehensions
Co-authored-by: Blaise Pabon <blaise@gmail.com> Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
1 parent b053937 commit 30228c5

1 file changed

Lines changed: 138 additions & 17 deletions

File tree

Doc/reference/expressions.rst

Lines changed: 138 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,6 @@ Formally, the syntax for groups is:
360360
group: '(' `assignment_expression` ')'
361361

362362

363-
.. _comprehensions:
364363
.. _displays:
365364

366365
Container displays
@@ -380,8 +379,10 @@ square brackets::
380379

381380
>>> ["one", "two", "three"]
382381
['one', 'two', 'three']
382+
>>> [1 + 2, 2 + 3]
383+
[3, 5]
383384

384-
In list, tuple and dictionary displays, the series may be empty::
385+
In list, tuple and dictionary (but not set) displays, the series may be empty::
385386

386387
>>> [] # empty list
387388
[]
@@ -419,20 +420,21 @@ left to right and placed into a new container of the appropriate type.
419420
pair: iterable; unpacking
420421
single: * (asterisk); in expression lists
421422

422-
For tuple, list and set displays, any item in the display may be prefixed
423-
with an asterisk (``*``).
423+
For tuple, list and set (but not dict) displays, any item in the display may
424+
be prefixed with an asterisk (``*``).
424425
This denotes :ref:`iterable unpacking <iterable-unpacking>`.
425426
At runtime, the asterisk-prefixed expression must evaluate to an iterable,
426427
whose contents are inserted into the container at the location of
427428
the unpacking. For example::
428429

429430
>>> numbers = (1, 2)
430431
>>> [*numbers, 'word', *numbers]
431-
(1, 2, 'word', 1, 2)
432+
[1, 2, 'word', 1, 2]
432433

433434
Dictionary displays use a similar mechanism called
434-
:ref:`dictionary unpacking <dict-unpacking>`, denoted with a double
435+
*dictionary unpacking*, denoted with a double
435436
asterisk (``**``).
437+
See :ref:`dict` for details.
436438

437439
A more advanced form of displays are :dfn:`comprehensions`, where items are
438440
computed via a set of looping and filtering instructions.
@@ -501,6 +503,7 @@ See :ref:`displays` for general information on displays.
501503
There is no special syntax for the empty set.
502504
The ``{}`` literal is a :ref:`dictionary display <dict>` that constructs an
503505
empty dictionary.
506+
Call :class:`set() <set>` with no arguments to get an empty set.
504507

505508
The formal grammar for set displays is:
506509

@@ -527,9 +530,6 @@ parentheses. For example::
527530

528531
>>> (1, 2)
529532
(1, 2)
530-
>>> ('one', 'two', 'thr' + 'ee')
531-
('one', 'two', 'three')
532-
533533
>>> () # an empty tuple
534534
()
535535

@@ -606,7 +606,12 @@ comprehension, and the final dictionary's value for a given key will be the
606606
last one given.
607607
For example::
608608

609-
>>> {1: 'this will be overridden', 2: 'two', 1: 'also overridden', 1: 'one'}
609+
>>> {
610+
... 1: 'this will be overridden',
611+
... 2: 'two',
612+
... 1: 'also overridden',
613+
... 1: 'one',
614+
... }
610615
{1: 'one', 2: 'two'}
611616

612617
.. index::
@@ -638,10 +643,133 @@ This may be used to override a set of defaults::
638643
Unpacking into dictionary displays, originally proposed by :pep:`448`.
639644

640645

646+
.. index::
647+
single: for; in comprehensions
648+
single: if; in comprehensions
649+
single: async for; in comprehensions
650+
651+
.. _comprehensions:
641652

642653
Comprehensions
643654
--------------
644655

656+
List, set and dictionary :dfn:`comprehensions` are a form of :ref:`displays`,
657+
where items are computed via a set of looping and filtering instructions
658+
rather than listed explicitly.
659+
660+
In its simplest form, a comprehension consists of a single expression
661+
followed by a :keyword:`!for` clause, all enclosed in paired delimiters.
662+
For example, a list of the first ten squares is::
663+
664+
>>> [x**2 for x in range(10)]
665+
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
666+
667+
A set of lowercase letters::
668+
669+
>>> {x.lower() for x in ('a', 'A', 'b', 'C')}
670+
{'c', 'a', 'b'}
671+
672+
A dict mapping some function names to functions::
673+
674+
>>> {f.__name__: f for f in (print, hex, any)}
675+
{'print': <built-in function print>,
676+
'hex': <built-in function hex>,
677+
'any': <built-in function any>}
678+
679+
There are no *tuple comprehensions*; a similar syntax is instead used
680+
for :ref:`generator expressions <genexpr>`.
681+
682+
Unpacking in comprehensions
683+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
684+
685+
Filtering in comprehensions
686+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
687+
688+
The :keyword:`!for` clause may be followed by an :keyword:`!if` clause
689+
with an expression.
690+
691+
For example, a list of names from the :mod:`math` module
692+
that start with `f` is::
693+
694+
>>> [name for name in vars(math) if name.startswith('f')]
695+
['fabs', 'factorial', 'floor', 'fma', 'fmod', 'frexp', 'fsum']
696+
697+
Complex comprehensions
698+
^^^^^^^^^^^^^^^^^^^^^^
699+
700+
The :keyword:`!for` clause may be followed zero or more additional
701+
:keyword:`!for` or :keyword:`!if` clauses.
702+
For example, here is a list of names exposed by two Python modules
703+
that start with ``a``::
704+
705+
>>> import math
706+
>>> import array
707+
>>> [
708+
... name
709+
... for module in (array, math)
710+
... for name in vars(module)
711+
... if name.startswith('a')
712+
... ]
713+
['array', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh']
714+
715+
716+
Asynchronous comprehensions
717+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
718+
719+
TODO: When a comprehension is evaluated,
720+
TODO: - scopes
721+
TODO: async for (& await)
722+
723+
>>> system_defaults = {'color': 'blue', 'count': 8}
724+
>>> user_defaults = {'color': 'yellow'}
725+
>>> overrides = {'count': 5}
726+
727+
>>> {**d for d in (system_defaults, user_defaults, overrides)}
728+
{'color': 'yellow', 'count': 5}
729+
730+
731+
at least one
732+
:keyword:`!for` clause and zero or more :keyword:`!for` or :keyword:`!if`
733+
clauses. In this case, the elements of the new container are those that would
734+
be produced by considering each of the :keyword:`!for` or :keyword:`!if`
735+
clauses a block, nesting from left to right, and evaluating the expression to
736+
produce an element each time the innermost block is reached. If the expression
737+
is starred, the result will instead be unpacked to produce zero or more
738+
elements.
739+
740+
However, aside from the iterable expression in the leftmost :keyword:`!for` clause,
741+
the comprehension is executed in a separate implicitly nested scope. This ensures
742+
that names assigned to in the target list don't "leak" into the enclosing scope.
743+
744+
The iterable expression in the leftmost :keyword:`!for` clause is evaluated
745+
directly in the enclosing scope and then passed as an argument to the implicitly
746+
nested scope. Subsequent :keyword:`!for` clauses and any filter condition in the
747+
leftmost :keyword:`!for` clause cannot be evaluated in the enclosing scope as
748+
they may depend on the values obtained from the leftmost iterable. For example:
749+
``[x*y for x in range(10) for y in range(x, x+10)]``.
750+
751+
To ensure the comprehension always results in a container of the appropriate
752+
type, ``yield`` and ``yield from`` expressions are prohibited in the implicitly
753+
nested scope.
754+
755+
.. index::
756+
single: await; in comprehensions
757+
758+
Since Python 3.6, in an :keyword:`async def` function, an :keyword:`!async for`
759+
clause may be used to iterate over a :term:`asynchronous iterator`.
760+
A comprehension in an :keyword:`!async def` function may consist of either a
761+
:keyword:`!for` or :keyword:`!async for` clause following the leading
762+
expression, may contain additional :keyword:`!for` or :keyword:`!async for`
763+
clauses, and may also use :keyword:`await` expressions.
764+
765+
If a comprehension contains :keyword:`!async for` clauses, or if it contains
766+
:keyword:`!await` expressions or other asynchronous comprehensions anywhere except
767+
the iterable expression in the leftmost :keyword:`!for` clause, it is called an
768+
:dfn:`asynchronous comprehension`. An asynchronous comprehension may suspend the
769+
execution of the coroutine function in which it appears.
770+
See also :pep:`530`.
771+
772+
645773
TODO
646774

647775

@@ -695,8 +823,6 @@ prevails.
695823

696824

697825

698-
There are no *tuple comprehensions*; a similar syntax is instead used
699-
for :ref:`generator expressions <genexpr>`.
700826

701827

702828
..
@@ -708,11 +834,6 @@ for :ref:`generator expressions <genexpr>`.
708834
* they are computed via a set of looping and filtering instructions, called a
709835
:dfn:`comprehension`.
710836

711-
.. index::
712-
single: for; in comprehensions
713-
single: if; in comprehensions
714-
single: async for; in comprehensions
715-
716837
Common syntax elements for comprehensions are:
717838

718839
.. productionlist:: python-grammar

0 commit comments

Comments
 (0)