views:

109

answers:

2

Am I missing something here? Why shouldn't the code under the "Broken" section work? I'm using Python 2.6.

#!/usr/bin/env python

def func(a,b,c):
    print a,b,c

#Working: Example #1:

p={'c':3}

func(1,
     b=2,
     c=3,
     )

#Working: Example #2:

func(1,
     b=2,
     **p)

#Broken: Example #3:

func(1,
     b=2,
     **p,
     )
+7  A: 

This is the relevant bit from the grammar:

arglist: (argument ',')* (argument [',']
                         |'*' test (',' argument)* [',' '**' test] 
                         |'**' test)

The first line here allows putting a comma after the last parameter when not using varargs/kwargs (this is why your first example works). However, you are not allowed to place a comma after the kwargs parameter if it is specified, as shown in the second and third lines.

By the way, here is an interesting thing shown by the grammar:

These are both legal:

f(a=1, b=2, c=3,)
f(*v, a=1, b=2, c=3)

but this is not:

f(*v, a=1, b=2, c=3,)

It makes sense not to allow a comma after **kwargs, since it must always be the last parameter. I don't know why the language designers chose not to allow my last example though - maybe an oversight?

interjay
+4  A: 

Python usually allows extra commas at the end of comma-lists (in argument lists and container literals). The main goal for this is to make code generation slightly easier (you don't have to special-case the last item or double-special-case a singleton tuple).

In the definition of the grammar, **kwargs is pulled out separately and without an extra optional comma. It wouldn't ever help with anything practical like code generation (**kwargs will always be the last thing so you do not have to special-case anything) as far as I can imagine, so I don't know why Python would support it.

Mike Graham