[Python-ideas] A sorted version of **kwargs

Nick Coghlan ncoghlan at gmail.com
Fri Jan 21 01:54:23 CET 2011

On Fri, Jan 21, 2011 at 2:42 AM, Guido van Rossum <guido at python.org> wrote:
> On Thu, Jan 20, 2011 at 6:05 AM, M.-A. Lemburg <mal at egenix.com> wrote:
>> Nick Coghlan wrote:
>>> Yeah, simply making the kwargs dict always ordered is likely the way
>>> we would do it. That's also the only solution with any chance of
>>> working by default with the way most decorators are structured
>>> (accepting *args and **kwargs and passing them to the wrapped
>>> function).
>> -1.
>> How often do you really need this ?
>> In which of those cases wouldn't a static code analysis give you
>> the call order of the parameters already  ?
>> "Nice to have" is not good enough to warrant a slow down of
>> all function calls involving keyword arguments, adding overhead
>> for other Python implementations and possibly causing problems
>> with 3rd party extensions relying on getting a PyDict for the
>> keyword arguments object.
> What he says.

I actually agree as well, but I was misremembering how the
construction of the kwargs dict worked and hence was thinking that was
the only possible way this could work (since the interpreter didn't
know anything about the target function while building the dict).
Actually checking with dis.dis and looking at the associated code in
ceval.c corrected my misapprehension (the function is actually
retrieved first, while the kwargs are still on the stack in the
appropriate order, so it is theoretically possible for the function to
influence how the args are stored).

So, as an alternative proposal, perhaps it would be possible to add a
new protocol that allowed a callable to flag that an ordered
dictionary should be used for kwargs (e.g. an "__ordered_call__"
boolean attribute, with C level flags to speed up the common builtin
callable cases). A @functools.ordered_call decorator could then just
do "__ordered_call__ = True" to set the flag appropriately. (You could
also be even more flexible and devise a protocol that supported any
type for kwargs, but I think that would just be far more complicated
without a corresponding increase in expressive power)

Ordinary calls that used "x=y" or "**d" would be slowed down
marginally due to the check for the new attribute on the supplied
callable, but that impact should be minimal (especially for the
builtin cases, which would just be checking a C struct field) and
other calls would be entirely unaffected.

The CPython specific impact would largely be limited to
update_keyword_args() and implementing C level fields with associated
__ordered_call__ properties on the various builtin callable objects.
There would also need to be a new variant of PyEval_EvalCodeEx that
either used an ordered dictionary for kwdict, or else allowed kwdict
to be created and passed in by the calling code rather than implicitly
created via PyDict_New().

A builtin version of collections.OrderedDict would still be a
precursor to this idea though, so creating a _collections.OrderedDict
C implementation still sounds like the right starting point for anyone
that is particularly keen to see this idea progress.


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list