Update to PEP 448 -- approved 2 out of 3, rejected *comprehension.
This commit is contained in:
parent
f2db585e09
commit
401c977971
113
pep-0448.txt
113
pep-0448.txt
|
@ -4,11 +4,11 @@ Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: Joshua Landau <joshua@landau.ws>
|
Author: Joshua Landau <joshua@landau.ws>
|
||||||
Discussions-To: python-ideas@python.org
|
Discussions-To: python-ideas@python.org
|
||||||
Status: Draft
|
Status: Accepted
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
Content-Type: text/x-rst
|
Content-Type: text/x-rst
|
||||||
Created: 29-Jun-2013
|
Created: 29-Jun-2013
|
||||||
Python-Version: 3.4
|
Python-Version: 3.5
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,15 +50,9 @@ In dictionaries, later values will always override earlier ones::
|
||||||
>>> {**{'x': 2}, 'x': 1}
|
>>> {**{'x': 2}, 'x': 1}
|
||||||
{'x': 1}
|
{'x': 1}
|
||||||
|
|
||||||
Unpacking is proposed to be allowed inside list, set,
|
This PEP does not include unpacking operators inside list, set and
|
||||||
and dictionary comprehensions::
|
dictionary comprehensions although this has not been ruled out for
|
||||||
|
future proposals.
|
||||||
>>> ranges = [range(i) for i in range(5)]
|
|
||||||
>>> [*item for item in ranges]
|
|
||||||
[0, 0, 1, 0, 1, 2, 0, 1, 2, 3]
|
|
||||||
|
|
||||||
>>> {*item for item in ranges}
|
|
||||||
{0, 1, 2, 3}
|
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
@ -121,14 +115,6 @@ list(my_range)`` which is now equivalent to just ``[*my_list,
|
||||||
*my_tuple, *my_range]``.
|
*my_tuple, *my_range]``.
|
||||||
|
|
||||||
|
|
||||||
The addition of unpacking to comprehensions is a logical extension.
|
|
||||||
It's usage will primarily be a neat replacement for ``[i for j in
|
|
||||||
list_of_lists for i in j]``, as the more readable
|
|
||||||
``[*l for l in list_of_lists]``. The iterable version,
|
|
||||||
``(*l for l in list_of_lists)``, replaces ``itertools.chain.from_iterable``.
|
|
||||||
Other uses are possible, but expected to occur rarely.
|
|
||||||
|
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
@ -145,7 +131,8 @@ Currently, if an argument is given multiple times — such as a
|
||||||
positional argument given both positionally and by keyword — a
|
positional argument given both positionally and by keyword — a
|
||||||
``TypeError`` is raised. This remains true for duplicate arguments
|
``TypeError`` is raised. This remains true for duplicate arguments
|
||||||
provided through multiple ``**`` unpackings,
|
provided through multiple ``**`` unpackings,
|
||||||
e.g. ``f(**{'x': 2}, **{'x': 3})``.
|
e.g. ``f(**{'x': 2}, **{'x': 3})``, except that the error will be
|
||||||
|
detected at runtime.
|
||||||
|
|
||||||
A function looks like this::
|
A function looks like this::
|
||||||
|
|
||||||
|
@ -159,34 +146,11 @@ Tuples, lists, sets and dictionaries will allow unpacking. This will
|
||||||
act as if the elements from unpacked items were inserted in order at
|
act as if the elements from unpacked items were inserted in order at
|
||||||
the site of unpacking, much as happens in unpacking in a function-call.
|
the site of unpacking, much as happens in unpacking in a function-call.
|
||||||
Dictionaries require ``**`` unpacking; all the others require ``*`` unpacking.
|
Dictionaries require ``**`` unpacking; all the others require ``*`` unpacking.
|
||||||
A dictionary's key remain in a right-to-left priority order, so
|
|
||||||
|
The keys in a dictionary remain in a right-to-left priority order, so
|
||||||
``{**{'a': 1}, 'a': 2, **{'a': 3}}`` evaluates to ``{'a': 3}``. There
|
``{**{'a': 1}, 'a': 2, **{'a': 3}}`` evaluates to ``{'a': 3}``. There
|
||||||
is no restriction on the number or position of unpackings.
|
is no restriction on the number or position of unpackings.
|
||||||
|
|
||||||
Comprehensions, by simple extension, will support unpacking. As before,
|
|
||||||
dictionaries require ``**`` unpacking, all the others require ``*``
|
|
||||||
unpacking and key priorities are unchanged.
|
|
||||||
|
|
||||||
For example::
|
|
||||||
|
|
||||||
{*[1, 2, 3], 4, 5, *{6, 7, 8}}
|
|
||||||
|
|
||||||
(*e for e in [[1], [3, 4, 5], [2]])
|
|
||||||
|
|
||||||
{**dictionary for dictionary in (globals(), locals())}
|
|
||||||
|
|
||||||
{**locals(), "override": None}
|
|
||||||
|
|
||||||
Unbracketed comprehensions in function calls, such as ``f(x for x in it)``,
|
|
||||||
are already valid. These could be extended to::
|
|
||||||
|
|
||||||
f(*x for x in it) == f((*x for x in it))
|
|
||||||
f(**x for x in it) == f({**x for x in it})
|
|
||||||
|
|
||||||
However, this is likely to be confusing and is not included in this
|
|
||||||
PEP. These will throw ``SyntaxError`` and comprehensions with explicit
|
|
||||||
brackets should be used instead.
|
|
||||||
|
|
||||||
|
|
||||||
Disadvantages
|
Disadvantages
|
||||||
=============
|
=============
|
||||||
|
@ -200,24 +164,75 @@ Whilst ``*elements, = iterable`` causes ``elements`` to be a list,
|
||||||
``elements = *iterable,`` causes ``elements`` to be a tuple. The
|
``elements = *iterable,`` causes ``elements`` to be a tuple. The
|
||||||
reason for this may confuse people unfamiliar with the construct.
|
reason for this may confuse people unfamiliar with the construct.
|
||||||
|
|
||||||
|
Concerns have been raised about the unexpected difference between
|
||||||
|
duplicate keys in dictionaries being allowed but duplicate keys
|
||||||
|
in function call syntax raising an error. Although this is already
|
||||||
|
the case with current syntax, this proposal might exacerbate the
|
||||||
|
issue. It remains to be seen how much of an issue this is in practice.
|
||||||
|
|
||||||
|
|
||||||
|
Variations
|
||||||
|
==========
|
||||||
|
|
||||||
|
The PEP originally considered whether the ordering of argument types
|
||||||
|
in a function call (positional, keyword, ``*`` or ``**``) could become
|
||||||
|
less strict. This met little support so the idea was shelved.
|
||||||
|
|
||||||
|
Earlier iterations of this PEP allowed unpacking operators inside
|
||||||
|
list, set, and dictionary comprehensions as a flattening operator
|
||||||
|
over iterables of containers::
|
||||||
|
|
||||||
|
>>> ranges = [range(i) for i in range(5)]
|
||||||
|
>>> [*item for item in ranges]
|
||||||
|
[0, 0, 1, 0, 1, 2, 0, 1, 2, 3]
|
||||||
|
|
||||||
|
>>> {*item for item in ranges}
|
||||||
|
{0, 1, 2, 3}
|
||||||
|
|
||||||
|
This was met with a mix of strong concerns about readability and mild
|
||||||
|
support. In order not to disadvantage the less controversial aspects
|
||||||
|
of the PEP, this was not accepted with the rest of the proposal.
|
||||||
|
|
||||||
|
Unbracketed comprehensions in function calls, such as ``f(x for x in it)``,
|
||||||
|
are already valid. These could be extended to::
|
||||||
|
|
||||||
|
f(*x for x in it) == f((*x for x in it))
|
||||||
|
f(**x for x in it) == f({**x for x in it})
|
||||||
|
|
||||||
|
However, it wasn't clear if this was the best behaviour or if it should
|
||||||
|
unpack into the arguments of the call to `f`. Since this is likely to be
|
||||||
|
confusing and is of only very marginal utility, it is not included in this
|
||||||
|
PEP. Instead, these will throw a ``SyntaxError`` and comprehensions with
|
||||||
|
explicit brackets should be used instead.
|
||||||
|
|
||||||
|
|
||||||
|
Approval
|
||||||
|
========
|
||||||
|
|
||||||
|
This PEP was accepted by Guido on February 25, 2015 [1]_.
|
||||||
|
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
==============
|
==============
|
||||||
|
|
||||||
An implementation for Python 3.5 is found at Issue 2292 on bug tracker [1]_.
|
An implementation for Python 3.5 is found at Issue 2292 on bug tracker [2]_.
|
||||||
|
This currently includes support for unpacking inside comprehensions, which
|
||||||
|
should be removed.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
==========
|
==========
|
||||||
|
|
||||||
.. [1] Issue 2292, "Missing `*`-unpacking generalizations", Thomas Wouters
|
.. [1] PEP accepted, "PEP 448 review", Guido van Rossum
|
||||||
|
(https://mail.python.org/pipermail/python-dev/2015-February/138564.html)
|
||||||
|
|
||||||
|
.. [2] Issue 2292, "Missing `*`-unpacking generalizations", Thomas Wouters
|
||||||
(http://bugs.python.org/issue2292)
|
(http://bugs.python.org/issue2292)
|
||||||
|
|
||||||
.. [2] Discussion on Python-ideas list,
|
.. [3] Discussion on Python-ideas list,
|
||||||
"list / array comprehensions extension", Alexander Heger
|
"list / array comprehensions extension", Alexander Heger
|
||||||
(http://mail.python.org/pipermail/python-ideas/2011-December/013097.html)
|
(http://mail.python.org/pipermail/python-ideas/2011-December/013097.html)
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue