Skip to content

Commit 8bfa487

Browse files
author
benjamin.peterson
committed
allow keyword args to be passed in after *args #3473
git-svn-id: http://svn.python.org/projects/python/trunk@65872 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 2b1ee30 commit 8bfa487

File tree

5 files changed

+29
-12
lines changed

5 files changed

+29
-12
lines changed

Doc/reference/expressions.rst

+10-9
Original file line numberDiff line numberDiff line change
@@ -625,11 +625,11 @@ of arguments:
625625
call: `primary` "(" [`argument_list` [","]
626626
: | `expression` `genexpr_for`] ")"
627627
argument_list: `positional_arguments` ["," `keyword_arguments`]
628-
: ["," "*" `expression`]
629-
: ["," "**" `expression`]
628+
: ["," "*" `expression`] ["," `keyword_arguments`]
629+
: ["," "**" `expression`]
630630
: | `keyword_arguments` ["," "*" `expression`]
631-
: ["," "**" `expression`]
632-
: | "*" `expression` ["," "**" `expression`]
631+
: ["," "**" `expression`]
632+
: | "*" `expression` ["," "*" `expression`] ["," "**" `expression`]
633633
: | "**" `expression`
634634
positional_arguments: `expression` ("," `expression`)*
635635
keyword_arguments: `keyword_item` ("," `keyword_item`)*
@@ -686,12 +686,13 @@ there were no excess keyword arguments.
686686

687687
If the syntax ``*expression`` appears in the function call, ``expression`` must
688688
evaluate to a sequence. Elements from this sequence are treated as if they were
689-
additional positional arguments; if there are positional arguments *x1*,...,*xN*
690-
, and ``expression`` evaluates to a sequence *y1*,...,*yM*, this is equivalent
691-
to a call with M+N positional arguments *x1*,...,*xN*,*y1*,...,*yM*.
689+
additional positional arguments; if there are positional arguments *x1*,...,
690+
*xN*, and ``expression`` evaluates to a sequence *y1*, ..., *yM*, this is
691+
equivalent to a call with M+N positional arguments *x1*, ..., *xN*, *y1*, ...,
692+
*yM*.
692693

693-
A consequence of this is that although the ``*expression`` syntax appears
694-
*after* any keyword arguments, it is processed *before* the keyword arguments
694+
A consequence of this is that although the ``*expression`` syntax may appear
695+
*after* some keyword arguments, it is processed *before* the keyword arguments
695696
(and the ``**expression`` argument, if any -- see below). So::
696697

697698
>>> def f(a, b):

Grammar/Grammar

+3-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ dictmaker: test ':' test (',' test ':' test)* [',']
130130

131131
classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
132132

133-
arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)
133+
arglist: (argument ',')* (argument [',']
134+
|'*' test (',' argument)* [',' '**' test]
135+
|'**' test)
134136
argument: test [gen_for] | test '=' test # Really [keyword '='] test
135137

136138
list_iter: list_for | list_if

Lib/test/test_grammar.py

+8
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,14 @@ def d31v((x)): pass
282282
def d32v((x,)): pass
283283
d32v((1,))
284284

285+
# keyword arguments after *arglist
286+
def f(*args, **kwargs):
287+
return args, kwargs
288+
self.assertEquals(f(1, x=2, *[3, 4], y=5), ((1, 3, 4),
289+
{'x':2, 'y':5}))
290+
self.assertRaises(SyntaxError, eval, "f(1, *(2,3), 4)")
291+
self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)")
292+
285293
# Check ast errors in *args and *kwargs
286294
check_syntax_error(self, "f(*g(1=2))")
287295
check_syntax_error(self, "f(**g(1=2))")

Python/ast.c

+5
Original file line numberDiff line numberDiff line change
@@ -1898,6 +1898,11 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
18981898
"non-keyword arg after keyword arg");
18991899
return NULL;
19001900
}
1901+
if (vararg) {
1902+
ast_error(CHILD(ch, 0),
1903+
"only named arguments may follow *expression");
1904+
return NULL;
1905+
}
19011906
e = ast_for_expr(c, CHILD(ch, 0));
19021907
if (!e)
19031908
return NULL;

Python/graminit.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,8 @@ static arc arcs_74_5[2] = {
16091609
static arc arcs_74_6[1] = {
16101610
{0, 6},
16111611
};
1612-
static arc arcs_74_7[1] = {
1612+
static arc arcs_74_7[2] = {
1613+
{162, 5},
16131614
{31, 3},
16141615
};
16151616
static state states_74[8] = {
@@ -1620,7 +1621,7 @@ static state states_74[8] = {
16201621
{4, arcs_74_4},
16211622
{2, arcs_74_5},
16221623
{1, arcs_74_6},
1623-
{1, arcs_74_7},
1624+
{2, arcs_74_7},
16241625
};
16251626
static arc arcs_75_0[1] = {
16261627
{28, 1},

0 commit comments

Comments
 (0)