On 05/23/2013 04:52 PM, Terry Jan Reedy wrote:
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

To be clear, you're saying that

     func(**{'foo bar baz':3})

is not supported (officially), but it works in CPython because checking that every string in the dict is a valid identifier would be costly. Of course that is sensible and I don't think the behaviour should be changed "to the detriment of sensible programmers". However, it would be nice if it was documented somewhere that the above function call is something that a non-sensible programmer would do. Perhaps with a "CPython implementation detail" type of block.
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to