# HG changeset patch # Parent 12d939477b4f9553cf68eb7db27b33334e1f51ed Issue #24136: Document generalized unpacking, PEP 448 Based on patches by Konstantin Molchanov and Neil Girdhar. diff -r 12d939477b4f Doc/library/functools.rst --- a/Doc/library/functools.rst Tue Jun 07 21:20:39 2016 +0100 +++ b/Doc/library/functools.rst Sat Jun 11 05:14:27 2016 +0000 @@ -176,7 +176,7 @@ def newfunc(*fargs, **fkeywords): newkeywords = keywords.copy() newkeywords.update(fkeywords) - return func(*(args + fargs), **newkeywords) + return func(*args, *fargs, **newkeywords) newfunc.func = func newfunc.args = args newfunc.keywords = keywords diff -r 12d939477b4f Doc/reference/expressions.rst --- a/Doc/reference/expressions.rst Tue Jun 07 21:20:39 2016 +0100 +++ b/Doc/reference/expressions.rst Sat Jun 11 05:14:27 2016 +0000 @@ -133,9 +133,9 @@ A parenthesized form is an optional expression list enclosed in parentheses: .. productionlist:: - parenth_form: "(" [`expression_list`] ")" + parenth_form: "(" [`starred_expression`] ")" -A parenthesized expression list yields whatever that expression list yields: if +A parenthesized expression list yields whatever that expression yields: if the list contains at least one comma, it yields a tuple; otherwise, it yields the single expression that makes up the expression list. @@ -202,7 +202,7 @@ brackets: .. productionlist:: - list_display: "[" [`expression_list` | `comprehension`] "]" + list_display: "[" [`starred_list` | `comprehension`] "]" A list display yields a new list object, the contents being specified by either a list of expressions or a comprehension. When a comma-separated list of @@ -223,7 +223,7 @@ displays by the lack of colons separating keys and values: .. productionlist:: - set_display: "{" (`expression_list` | `comprehension`) "}" + set_display: "{" (`starred_list` | `comprehension`) "}" A set display yields a new mutable set object, the contents being specified by either a sequence of expressions or a comprehension. When a comma-separated @@ -250,7 +250,7 @@ .. productionlist:: dict_display: "{" [`key_datum_list` | `dict_comprehension`] "}" key_datum_list: `key_datum` ("," `key_datum`)* [","] - key_datum: `expression` ":" `expression` + key_datum: `expression` ":" `expression` | "**" `or_expr` dict_comprehension: `expression` ":" `expression` `comp_for` A dictionary display yields a new dictionary object. @@ -261,6 +261,16 @@ that you can specify the same key multiple times in the key/datum list, and the final dictionary's value for that key will be the last one given. +.. index:: unpacking; dictionary, **; in dictionary displays + +A double asterisk ``**`` denotes :dfn:`dictionary unpacking`. +Its operand must be a :term:`mapping`. Each mapping item is added +to the new dictionary. Later values replace values already set by +earlier key/datum pairs and earlier dictionary unpackings. + +.. versionadded:: 3.5 + Unpacking into dictionary displays, originally proposed by :pep:`448`. + A dict comprehension, in contrast to list and set comprehensions, needs two expressions separated with a colon followed by the usual "for" and "if" clauses. When the comprehension is run, the resulting key and value elements are inserted @@ -649,15 +659,15 @@ .. productionlist:: call: `primary` "(" [`argument_list` [","] | `comprehension`] ")" - argument_list: `positional_arguments` ["," `keyword_arguments`] - : ["," "*" `expression`] ["," `keyword_arguments`] - : ["," "**" `expression`] - : | `keyword_arguments` ["," "*" `expression`] - : ["," `keyword_arguments`] ["," "**" `expression`] - : | "*" `expression` ["," `keyword_arguments`] ["," "**" `expression`] - : | "**" `expression` - positional_arguments: `expression` ("," `expression`)* - keyword_arguments: `keyword_item` ("," `keyword_item`)* + argument_list: `positional_arguments` ["," `starred_and_keywords`] + : ["," `keywords_arguments`] + : | `starred_and_keywords` ["," `keywords_arguments`] + : | `keywords_arguments` + positional_arguments: ["*"] `expression` ("," ["*"] `expression`)* + starred_and_keywords: ("*" `expression` | `keyword_item`) + : ("," "*" `expression` | "," `keyword_item`)* + keywords_arguments: (`keyword_item` | "**" `expression`) + : ("," `keyword_item` | "**" `expression`)* keyword_item: `identifier` "=" `expression` An optional trailing comma may be present after the positional and keyword arguments @@ -715,17 +725,18 @@ .. index:: single: *; in function calls + single: unpacking; in function calls If the syntax ``*expression`` appears in the function call, ``expression`` must -evaluate to an iterable. Elements from this iterable are treated as if they -were additional positional arguments; if there are positional arguments -*x1*, ..., *xN*, and ``expression`` evaluates to a sequence *y1*, ..., *yM*, -this is equivalent to a call with M+N positional arguments *x1*, ..., *xN*, -*y1*, ..., *yM*. +evaluate to an :term:`iterable`. Elements from these iterables are +treated as if they were additional positional arguments. For the call +``f(x1, x2, *y, x3, x4)``, if *y* evaluates to a sequence *y1*, ..., *yM*, +this is equivalent to a call with M+4 positional arguments *x1*, *x2*, +*y1*, ..., *yM*, *x3*, *x4*. A consequence of this is that although the ``*expression`` syntax may appear -*after* some keyword arguments, it is processed *before* the keyword arguments -(and the ``**expression`` argument, if any -- see below). So:: +*after* explicit keyword arguments, it is processed *before* the +keyword arguments (and any ``**expression`` arguments -- see below). So:: >>> def f(a, b): ... print(a, b) @@ -746,13 +757,20 @@ single: **; in function calls If the syntax ``**expression`` appears in the function call, ``expression`` must -evaluate to a mapping, the contents of which are treated as additional keyword -arguments. In the case of a keyword appearing in both ``expression`` and as an -explicit keyword argument, a :exc:`TypeError` exception is raised. +evaluate to a :term:`mapping`, the contents of which are treated as +additional keyword arguments. If a keyword is already present +(as an explicit keyword argument, or from another unpacking), +a :exc:`TypeError` exception is raised. Formal parameters using the syntax ``*identifier`` or ``**identifier`` cannot be used as positional argument slots or as keyword argument names. +.. versionchanged:: 3.5 + Function calls accept any number of ``*`` and ``**`` unpackings, + positional arguments may follow iterable unpackings (``*``), + and keyword arguments may follow dictionary unpackings (``**``). + Originally proposed by :pep:`448`. + A call always returns some value, possibly ``None``, unless it raises an exception. How this value is computed depends on the type of the callable object. @@ -1407,13 +1425,29 @@ .. productionlist:: expression_list: `expression` ( "," `expression` )* [","] + starred_list: `starred_item` ( "," `starred_item` )* [","] + starred_expression: `expression` | ( `starred_item` "," )* [`starred_item`] + starred_item: `expression` | "*" `or_expr` .. index:: object: tuple -An expression list containing at least one comma yields a tuple. The length of +Except when part of a list or set display, an expression list +containing at least one comma yields a tuple. The length of the tuple is the number of expressions in the list. The expressions are evaluated from left to right. +.. index:: + pair: iterable; unpacking + single: *; in expression lists + +An asterisk ``*`` denotes :dfn:`iterable unpacking`. Its operand must be +an :term:`iterable`. The iterable is expanded into a sequence of items, +which are included in the new tuple, list, or set, at the site of +the unpacking. + +.. versionadded:: 3.5 + Iterable unpacking in expression lists, originally proposed by :pep:`448`. + .. index:: pair: trailing; comma The trailing comma is required only to create a single tuple (a.k.a. a diff -r 12d939477b4f Doc/reference/lexical_analysis.rst --- a/Doc/reference/lexical_analysis.rst Tue Jun 07 21:20:39 2016 +0100 +++ b/Doc/reference/lexical_analysis.rst Sat Jun 11 05:14:27 2016 +0000 @@ -619,7 +619,8 @@ .. productionlist:: f_string: (`literal_char` | "{{" | "}}" | `replacement_field`)* replacement_field: "{" `f_expression` ["!" `conversion`] [":" `format_spec`] "}" - f_expression: `conditional_expression` ("," `conditional_expression`)* [","] + f_expression: (`conditional_expression` | "*" `or_expr`) + : ("," `conditional_expression` | "," "*" `or_expr`)* [","] : | `yield_expression` conversion: "s" | "r" | "a" format_spec: (`literal_char` | NULL | `replacement_field`)* diff -r 12d939477b4f Doc/reference/simple_stmts.rst --- a/Doc/reference/simple_stmts.rst Tue Jun 07 21:20:39 2016 +0100 +++ b/Doc/reference/simple_stmts.rst Sat Jun 11 05:14:27 2016 +0000 @@ -45,7 +45,7 @@ expression statement is: .. productionlist:: - expression_stmt: `expression_list` + expression_stmt: `starred_expression` An expression statement evaluates the expression list (which may be a single expression). @@ -81,7 +81,7 @@ attributes or items of mutable objects: .. productionlist:: - assignment_stmt: (`target_list` "=")+ (`expression_list` | `yield_expression`) + assignment_stmt: (`target_list` "=")+ (`starred_expression` | `yield_expression`) target_list: `target` ("," `target`)* [","] target: `identifier` : | "(" [`target_list`] ")" @@ -892,7 +892,7 @@ nonlocal_stmt: "nonlocal" `identifier` ("," `identifier`)* .. XXX add when implemented - : ["=" (`target_list` "=")+ expression_list] + : ["=" (`target_list` "=")+ starred_expression] : | "nonlocal" identifier augop expression_list The :keyword:`nonlocal` statement causes the listed identifiers to refer to diff -r 12d939477b4f Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst Tue Jun 07 21:20:39 2016 +0100 +++ b/Doc/whatsnew/3.5.rst Sat Jun 11 05:14:27 2016 +0000 @@ -307,7 +307,7 @@ :pep:`448` extends the allowed uses of the ``*`` iterable unpacking operator and ``**`` dictionary unpacking operator. It is now possible -to use an arbitrary number of unpackings in function calls:: +to use an arbitrary number of unpackings in :ref:`function calls `:: >>> print(*[1], *[2], 3, *[4, 5]) 1 2 3 4 5 @@ -320,7 +320,7 @@ 1 2 3 4 Similarly, tuple, list, set, and dictionary displays allow multiple -unpackings:: +unpackings (see :ref:`exprlists` and :ref:`dict`):: >>> *range(4), 4 (0, 1, 2, 3, 4) diff -r 12d939477b4f Misc/NEWS --- a/Misc/NEWS Tue Jun 07 21:20:39 2016 +0100 +++ b/Misc/NEWS Sat Jun 11 05:14:27 2016 +0000 @@ -144,6 +144,11 @@ - Issue #23977: Add more asserts to test_delegator. +Documentation +------------- + +- Issue #24136: Document the new PEP 448 unpacking syntax of 3.5. + Tests -----