PEP 448: Updates from Neil Girdhar.

This commit is contained in:
Berker Peksag 2015-01-30 22:02:45 +02:00
parent dd8631553c
commit 0ee06e9bd1
1 changed files with 48 additions and 65 deletions

View File

@ -16,30 +16,22 @@ Abstract
========
This PEP proposes extended usages of the ``*`` iterable unpacking
operator to allow unpacking in more positions, an arbitrary number of
times, and in several additional circumstances.
operator and ``**`` dictionary unpacking operator
to allow unpacking in more positions, an arbitrary number of
times, and in additional circumstances. Specifically
in function calls, in comprehensions and generator expressions,
and in displays.
Specifically:
Arbitrarily positioned unpacking operators::
Function calls are proposed to support an arbitrary number of
unpackings rather than just one::
>>> print(*[1], *[2], 3)
1 2 3
>>> dict(**{'x': 1}, y=2, **{'z': 3})
{'x': 1, 'y': 2, 'z': 3}
Function calls currently have the restriction that keyword arguments
must follow positional arguments and ``**`` unpackings must additionally
follow ``*`` unpackings. Because of the new levity for ``*`` and ``**``
unpackings, it may be advisable to lift some or all of these
restrictions.
As currently, if an argument is given multiple times - such as a
positional argument given both positionally and by keyword - a
TypeError is raised.
Unpacking is proposed to be allowed inside tuples, lists, sets,
dictionaries and comprehensions::
Unpacking is proposed to be allowed inside tuple, list, set,
and dictionary displays::
>>> *range(4), 4
(0, 1, 2, 3, 4)
@ -50,10 +42,25 @@ dictionaries and comprehensions::
>>> {'x': 1, **{'y': 2}}
{'x': 1, 'y': 2}
In sets and dictionaries, this provides a concise overriding
notation::
>>> {'x': 1, **{'x': 2}}
{'x': 2}
>>> {**{'x': 2}, 'x': 1}
{'x': 1}
Unpacking is proposed to be allowed inside list, set,
and dictionary comprehensions::
>>> 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
=========
@ -124,38 +131,29 @@ Other uses are possible, but expected to occur rarely.
Specification
=============
Function calls may accept an unbound number of ``*`` and ``**``
Function calls may accept an unbounded number of ``*`` and ``**``
unpackings. There will be no restriction of the order of positional
arguments with relation to ``*`` unpackings nor any restriction of the
order of keyword arguments with relation to ``**`` unpackings.
Function calls currently have the restriction that keyword arguments
must follow positional arguments and ``**`` unpackings must additionally
follow ``*`` unpackings. Because of the new levity for ``*`` and ``**``
unpackings, it may be advisable to list some or all of these
restrictions.
follow ``*`` unpackings.
As currently, if an argument is given multiple times - such as a
positional argument given both positionally and by keyword - a
TypeError is raised.
Currently, if an argument is given multiple times — such as a
positional argument given both positionally and by keyword — a
``TypeError`` is raised. This remains true for duplicate arguments
provided through multiple keyword argument unpackings,
e.g. ``f(**{'x': 2}, **{'x': 3})``.
If the restrictions are kept, a function call will look like this::
A function looks like this::
function(
argument or *args, argument or *args, ...,
kwargument or *args, kwargument or *args, ...,
kwargument or **kwargs, kwargument or **kwargs, ...
)
If they are removed completely, a function call will look like this::
function(
argument or keyword_argument or *args or **kwargs,
argument or keyword_argument or *args or **kwargs,
...
argument or *args, argument or *args, ...,
kwargument or *args, kwargument or *args, ...,
kwargument or **kwargs, kwargument or **kwargs, ...
)
Tuples, lists, sets and dictionaries will allow unpacking. This will
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.
@ -168,7 +166,7 @@ Comprehensions, by simple extension, will support unpacking. As before,
dictionaries require ``**`` unpacking, all the others require ``*``
unpacking and key priorities are unchanged.
Examples include::
For example::
{*[1, 2, 3], 4, 5, *{6, 7, 8}}
@ -178,45 +176,30 @@ Examples include::
{**locals(), "override": None}
However, ``f(*x for x in it)`` and ``f(**x for x in it)`` continue
to raise SyntaxError.
Disadvantages
=============
If the current restrictions for function call arguments (keyword
arguments must follow positional arguments and ``**`` unpackings must
additionally follow ``*`` unpackings) are kept, the allowable orders
for arguments in a function call is more complicated than before.
The allowable orders for arguments in a function call is more
complicated than before.
The simplest explanation for the rules may be "positional arguments
come first and keyword arguments follow, but ``*`` unpackings are
allowed after keyword arguments".
come first and keyword arguments follow, but iterable unpackings are
allowed after keyword arguments" or "iterable arguments precede
all keyword arguments and keyword argument unpackings, and iterable
argument unpackings precede all keyword argument unpackings".
If the current restrictions are lifted, there are no obvious gains to
code as the only new orders that are allowed look silly: ``f(a, e=e,
d=d, b, c)`` being a simpler example.
Whilst ``*elements, = iterable`` causes ``elements`` to be a list,
While ``*elements, = iterable`` causes ``elements`` to be a list,
``elements = *iterable,`` causes ``elements`` to be a tuple. The
reason for this may not be obvious at first glance and may confuse
people unfamiliar with the construct.
reason for this may confuse people unfamiliar with the construct.
Implementation
==============
An implementation for an old version of Python 3 is found at Issue
2292 on bug tracker [1]_, although several changes should be made:
- It has yet to be updated to the most recent Python version
- It features a now redundant replacement for "yield from" which
should be removed
- It also loses support for calling function with keyword arguments before
positional arguments, which is an unnecessary backwards-incompatible change
- If the restrictions on the order of arguments in a function call are
partially or fully lifted, they would need to be included
An implementation for Python 3.5 is found at Issue 2292 on bug tracker [1]_.
References