[Python-Dev] Can Python guarantee the order of keyword-only parameters?

Larry Hastings larry at hastings.org
Mon Nov 27 12:05:57 EST 2017



First, a thirty-second refresher, so we're all using the same terminology:

    A *parameter* is a declared input variable to a function.
    An *argument* is a value passed into a function.  (*Arguments* are
    stored in *parameters.*)

    So in the example "def foo(clonk): pass; foo(3)", clonk is a
    parameter, and 3 is an argument. ++


Keyword-only arguments were conceived of as being unordered. They're 
stored in a dictionary--by convention called **kwargs--and dictionaries 
didn't preserve order.  But knowing the order of arguments is 
occasionally very useful.  PEP 468 proposed that Python preserve the 
order of keyword-only arguments in kwargs.  This became easy with the 
order-preserving dictionaries added to Python 3.6.  I don't recall the 
order of events, but in the end PEP 468 was accepted, and as of 3.6 
Python guarantees order in **kwargs.

But that's arguments.  What about parameters?

Although this isn't as directly impactful, the order of keyword-only 
parameters *is* visible to the programmer.  The best way to see a 
function's parameters is with inspect.signature, although there's also 
the deprecated inspect.getfullargspec; in CPython you can also directly 
examine fn.__code__.co_varnames.  Two of these methods present their 
data in a way that preserves order for all parameters, including 
keyword-only parameters--and the third one is deprecated.

Python must (and does) guarantee the order of positional and 
positional-or-keyword parameters, because it uses position to map 
arguments to parameters when the function is called.  But conceptually 
this isn't necessary for keyword-only parameters because their position 
is irrelevant.  I only see one place in the language & library that 
addresses the ordering of keyword-only parameters, by way of omission.  
The PEP for inspect.signature (PEP 362) says that when comparing two 
signatures for equality, their positional and positional-or-keyword 
parameters must be in the same order.  It makes a point of *not* 
requiring that the two functions' keyword-only parameters be in the same 
order.

For every currently supported version of Python 3, inspect.signature and 
fn.__code__.co_varnames preserve the order of keyword-only parameters.  
This isn't surprising; it's basically the same code path implementing 
those as the two types of positional-relevant parameters, so the most 
straightforward implementation would naturally preserve their order.  
It's just not guaranteed.

I'd like inspect.signature to guarantee that the order of keyword-only 
parameters always matches the order they were declared in.  Technically 
this isn't a language feature, it's a library feature.  But making this 
guarantee would require that CPython internally cooperate, so it's kind 
of a language feature too.

Does this sound reasonable?  Would it need a PEP?  I'm hoping for "yes" 
and "no", respectively.


Three final notes:

  * Yes, I do have a use case.  I'm using inspect.signature metadata to
    mechanically map arguments from an external domain (command-line
    arguments) to a Python function.  Relying on the declaration order
    of keyword-only parameters would elegantly solve one small problem.
  * I asked Armin Rigo about PyPy's support for Python 3.  He said it
    should already maintain the order of keyword-only parameters, and if
    I ever catch it not maintaining them in order I should file a bug. 
    I assert that making this guarantee would be nearly zero effort for
    any Python implementation--I bet they all already behave this way,
    all they need is a test case and some documentation.
  * One can extend this concept to functools.partial and
    inspect.Signature.bind: should its transformations of keyword-only
    parameters also maintain order in a consistent way?  I suspect the
    answer there is much the same--there's an obvious way it should
    behave, it almost certainly already behaves that way, but it doesn't
    guarantee it.  I don't think I need this for my use case.



//arry/

++ Yes, that means "Argument Clinic" should really have been called 
"Parameter Clinic".  But the "Parameter Clinic" sketch is nowhere near 
as funny.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20171127/af157416/attachment.html>


More information about the Python-Dev mailing list