First of all: the **{...}
call convention with non-identifier names only works if the called function has a **kw
argument to receive them, as it too cannot define explicit keyword arguments that are not valid identifiers.
I'd say that the keyword_arguments
grammar only applies to the parser of the source code, and cannot ever be seen as a functional restriction on the contents of the **expression
result. The functional description below does not restrict the keys of the dictionary explicitly, nor does the function definition documentation.
Instead, since the grammar allows an expression
, and the functional spec states that that should resolve to a mapping the contents of which are treated as additional keyword arguments, it is clear (to me) that there are no restrictions on the keys at all, beyond the normal ones applicable to Python dictionaries (keys must be immutable). You can pass in tuple or numeric keys for all Python cares. The functional spec states how the contents are treated, not that the contents must fit a certain format.
So, in my opinion the functional spec would have to explicitly restrict the keys in the **expression
dictionary to disallow what you are doing, because the grammar certainly does not. Changing that would be a huge backwards-incompatible change, and is not likely to ever be added.
Note that even though the spec doesn't mention any restrictions on the keys of the dictionary, CPython does:
>>> def f(*args, **kw): print args, kw
...
>>> f(**{1: 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() keywords must be strings
This is a restriction made by the python interpreter when invoking code objects (user defined functions). The reason why is explained in the source code right after the part that raises the above exception:
/* Speed hack: do raw pointer compares. As names are
normally interned this should almost always hit. */
By restricting keywords to strings a speed optimisation is possible.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…