[Python-ideas] Positional only arguments

Adam Olsen rhamph at gmail.com
Mon May 21 08:36:42 CEST 2007


On 5/20/07, Steven Bethard <steven.bethard at gmail.com> wrote:
> On 5/20/07, George Sakkis <george.sakkis at gmail.com> wrote:
> > Are you proposing the removal of positional-or-keyword arguments
>
> No. My current proposal is:
>
> - Everything after a * is a positional-only argument, up to the first **
> - Everything after a ** is a keyword-only argument
> - A lone * may only appear at the beginning of the signature
>
> In essence, this is changing the lone * of `PEP 3102`_ into a lone **,
> and allowing a lone * at the beginning of the signature to indicate
> that all positional arguments are positional-only.
>
> .. _PEP 3102: http://www.python.org/dev/peps/pep-3102/
>
> That means that in the following signature::
>
>     def f(*, a, b=None, *args, **, c=42, **kwargs)
>
> - 'a' and 'b' are positional-only
> - 'args' is positional-only (as usual)
> - 'c' is keyword-only
> - 'kwargs' is keyword-only (as usual)
>
> If you want positional-or-keyword arguments, simply omit the initial *::
>
>     def f(a, b=None, *args, **, c=42, **kwargs)

** is redundant here.  You get the same behaviour without it:

    def f(a, b=None, *args, c=42, **kwargs)

See below though.


> - 'a' and 'b' are positional-or-keyword (as usual)
> - 'args' is positional-only (as usual)
> - 'c' is keyword-only
> - 'kwargs' is keyword-only (as usual)
>
> If you want keyword-only arguments with no *args, simply omit it::
>
>     def f(a, b=None, **, c=42, **kwargs)
>
> - 'a' and 'b' are positional-or-keyword (as usual)
> - 'c' is keyword-only
> - 'kwargs' is keyword-only (as usual)
>
> Does anyone have use cases that this doesn't cover?

I initially had the same reservations you do about my proposal, but
now I think there's a bigger problem: it undermines the obviousness of
PEP 3102's behaviour.

Consider this example:

    def compare(a, b, *args, key=None):

Although not legal today, the behaviour is obvious.  All positional
arguments get sucked up in *args so key *must* be keyword-only.  That
leads to this variant:

    def compare(a, b, *, key=None):

You continue sucking up extra positional args, but since it's nameless
there must be none of them.  Again, obvious.  Changing the token
required from * to ** or giving * extra behaviour when nameless just
isn't obvious.

Most of the proposed syntax changes also have a question of whether or
not to include *args:
  "def f(a, *, *args)" or "def(a, *args, *)"?
  "def f((a), *args)" or "def f((a, *args))"?
  "def f(__a, *args)" or "def(__a, *__args)"?

Finally (I hope) is the problem of motivation.  Where as PEP 3102 is
motivated by "explicit is better than implicit", positional-only
arguments actually *want* implicit!  It seems to be more for
completeness and "C functions already support it".

-1 on any syntax changes.  A decorator may be okay, but I'm unsure the
use cases are significant enough to warrant adding it.  Go figure.

-- 
Adam Olsen, aka Rhamphoryncus



More information about the Python-ideas mailing list