[Python-ideas] loosening the restriction on what types may be unpacked using the ** syntax

Andrew Barnert abarnert at yahoo.com
Thu Apr 3 11:43:30 CEST 2014


Sorry, Yahoo interpreted some key combination as "Send". I think it's mostly readable as-is, but let me clarify a few things.

First, if you're proposing what I think you are, I like the idea. I don't know how useful it would be, but I don't see any real downside. So, +0.5.


And now, comments inline:

From: Andrew Barnert <abarnert at yahoo.com>
> From: Eric Snow <ericsnowcurrently at gmail.com>
> Sent: Wednesday, April 2, 2014 11:54 PM
> 
>> T he ** keyword arg unpacking syntax in function calls is useful.
>>  However, currently there is an explicit check for a mapping type
>>  (presumably PyMapping_Check).
> 
> Actually, I believe there's not really an explicit check. In CPython, 
> ext_do_call (hg.python.org/cpython/file/default/Python/ceval.c#l4463) uses 
> PyDict_Update (https://docs.python.org/3/c-api/dict.html#c.PyDict_Update) to 
> copy the kwargs argument to its empty dict, and PyDict_Update, unlike the Python 
> equivalent dict.update, "doesn’t fall back to the iterating over a sequence 
> of key value pairs if the second argument has no “keys” attribute." In 
> PyPy, the relevant code (in Arguments._combine_starstarargs_wrapped, 
> https://bitbucket.org/pypy/pypy/src/default/pypy/interpreter/argument.py#cl-95) 
> is different, but has the same effect (view_as_kwargs only works on mappings). I 
> don't know about other implementations.

However, the language reference does make this an explicit requirement. Section 6.3.4 (https://docs.python.org/3.4/reference/expressions.html#calls) says this:


> 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 TypeError exception is raised.

So basically, you just want to change that paragraph.

[snip]

… to:


>  If the syntax **expression appears in the function call, expression must
> evaluate to an iterable. If the iterable is a mapping, its contents are treated 
> as additional keyword
> arguments. Otherwise, each item in the iterable must itself be an iterator with 
> exactly two objects. The first object of each item is treated as an additional 
> keyword, and the second as that keyword's argument. In the case of a keyword 
> appearing in both expressionand as an
> explicit keyword argument, a TypeErrorexception is raised.


> As for implementation, that's also trivial. In CPython, just change 

> ext_do_call to try falling back to PyDict_MergeFromSeq2 if PyDict_Update returns 
> a TypeError. In PyPy, just change view_as_kwargs to work on iterables of 
> iterable pairs. And so on.


More information about the Python-ideas mailing list