Non-identifiers in dictionary keys for **expression syntax

Terry Jan Reedy tjreedy at udel.edu
Thu May 23 16:52:11 EDT 2013


On 5/23/2013 2:52 PM, Matthew Gilson wrote:
> This is a question regarding the documentation around dictionary
> unpacking.  The documentation for the call syntax
> (http://docs.python.org/3/reference/expressions.html#grammar-token-call)
> says:
>
> "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."
>
> That's fine, but what is a keyword argument?  According to the glossary
> (http://docs.python.org/3.3/glossary.html):
>
> /"keyword argument/: an argument preceded by an identifier (e.g. name=)
> in a function call or passed as a value in a dictionary preceded by **."

It appears that the requirement has been relaxed (in the previous 
quote), so that 'dictionary' should also be changed to 'mapping'. It 
might not hurt to add 'The key for the value should be an identifier.'
>
> As far as I'm concerned, this leads to some ambiguity in whether the
> keys of the mapping need to be valid identifiers or not.

I think you are being too lawyerly. The pretty clear and sensible 
implication is that the key for the value should be a string with a 
valid identifier. If it is anything else, you are on your own and 
deserve any joy or pain that results ;=)

> Using Cpython, we can do the following:
>
>       def func(**kwargs):
>            print kwargs
>
>       d = {'foo bar baz':3}
>
> So that might lead us to believe that the keys of the mapping do not
> need to be valid identifiers.

There are two ways to pass args to func to be gathered into kwargs; 
explicit key=val pairs and **mapping, or both.
func(a=1, b='hi', **{'foo bar baz':3})
#
{'foo bar baz': 3, 'a': 1, 'b': 'hi'}

So func should not expect anything other than identifier strings.

   However, the previous function does not
> work with the following dictionary:
>
>      d = {1:3}
>
> because not all the keys are strings.

So CPython checks that keys are strings, because that is cheap, but not 
that the strings are identifiers, because that would be more expensive. 
Just because an implementation allow somethings (omits a check) for 
efficiency does not mean you should do it.

globals()[1] = 1
works, but is not normally very sensible or useful.

>  Is there a way to petition to get this more rigorously defined?

bugs.python.org
The problem is that mandating a rigorous check by implementations makes 
Python slower to the detriment of sensible programmers.







More information about the Python-list mailing list