[Python-ideas] Preserving **kwargs order

MRAB python at mrabarnett.plus.com
Thu Mar 20 13:58:27 CET 2014


On 2014-03-20 06:43, Andrew Barnert wrote:
 > From: MRAB <python at mrabarnett.plus.com>
 >
 > Sent: Wednesday, March 19, 2014 7:42 PM
 >
 >
 > > On 2014-03-20 01:58, Andrew Barnert wrote:
 > >> On Mar 19, 2014, at 16:32,
 > >> Eric Snow <ericsnowcurrently at gmail.com> wrote:
 > >>>  Hopefully I'll have time to write a proto-PEP on this in the
 > >>>  next couple weeks, but the gist is that I see 2 options:
 > >>
 > >>  But it doesn't solve the main problem. Right now, you can forward
 > >>  any arguments perfectly by doing this:
 > >>
 > >>       def wrapper(*args, **kwargs):
 > >>           return wrappee(*args, **kwargs)
 > >>
 > >>  Your option 2 would require much more verbose code to forward
 > >>  perfectly.
 > >> … it would still break the thousands of wrapper functions out
 >
 > >>  there written with **kwargs.
 > >
 > > Wouldn't it be a problem only if the dict were unpacked and then
 > > repacked? In the code above, it's merely passing the input kwargs
 > > on to 'wrappee'.
 >
 > No, a **kwargs parameter packs the keyword arguments into a dict, and
 >  a **kwargs argument unpacks a dict into the keyword arguments;
 > that's exactly what they do. And dicts have arbitrary order.
 >
When I decompile, what I get is:

 >>> dis(compile('''wrappee(**kwargs)''', '<string>', 'exec'))
   1           0 LOAD_NAME                0 (wrappee)
               3 LOAD_NAME                1 (kwargs)
               6 CALL_FUNCTION_KW         0 (0 positional, 0 keyword pair)
               9 POP_TOP
              10 LOAD_CONST               0 (None)
              13 RETURN_VALUE

It looks like the dict 'kwargs' is being passed straight to 'wrappee'.

 > Besides, the whole point of option 2 is that kwargs is still just a
 > plain dict, and the order is passed via a magic hidden parameter
 > __kwargs_order__. So, even if you _were_ just passing kwargs on
 > without doing anything to it, that still wouldn't help. As long as
 > wrapper (and every other general-purpose wrapper every written)
 > doesn't do anything with __kwargs_order__, the order is not going to
 > get passed to wrapped.
 >
 > The obvious way to fix this is to make a **kwargs parameter pack the
 > keyword arguments into an OrderedDict, but Guido has already rejected
 > that, which is why Eric Snow had to come up with his two other
 > options. But they don't solve the problem.
 >



More information about the Python-ideas mailing list