[Python-ideas] keyword arguments everywhere (stdlib) - issue8706

Guido van Rossum guido at python.org
Sat Mar 3 04:31:06 CET 2012

On Fri, Mar 2, 2012 at 6:57 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> I believe that the right place to tag the parameter is in the parameter
> itself, not by adding an extra parameter after it. Hence, something like
> this:
> def spam(~x, ~y, ~z, ~a=2/3):
>    ...
> where ~name means that name cannot be specified by keyword. I read it as
> "not name", as in, the caller can't use the name.
> Or if you prefer Guido's pun:
> def spam(/x, /y, /z, /a=2/3):
>    ...
> Much less line-noise than spam(x, /, y, /, z, /, a=2/3, /).

That can't be right -- if a parameter is positional, surely all
parameters before it are also positional, so it would be redundant to
have to mark all of them up. Also ~name looks too much like an
expression and /name looks just weird (I think DOS command line flags
used to look like this).

> Personally, I think this is somewhat of an anti-feature. Keyword arguments
> are a Good Thing, and while I don't believe it is good enough to *force* all
> C functions to support them, I certainly don't want to discourage Python
> functions from supporting them.

And yet people invent decorators and other hacks to insist on
positional parameters all the time. You *can* have Too Much of a Good
Thing, and for readability it's better if calls are consistent. If
most calls to a function use positional arguments (at least for the
first N positions), it's better to force *all* calls to use positional
arguments 1-N: the reader may be unfamiliar with the parameter names.
Also remember the subclassing issue I brought up before.

That said, I can't come up with a syntax that I really like. Here's my
best attempt, but I'm at most -0 on it: Have a stand-alone '/'
indicate "all parameters to my left must be positional", just like a
stand-alone '*' means "all parameters to my right must be keywords".
If there's no stand-alone '*' it is assumed to be all the way on the
right; so if there's no '/' it is assumed to be all the way on the
left. The following should all be valid:

def foo(/, a, b): ...  # edge case, same as def foo(a, b): ...

def foo(a, b, /): ...  # all positional

def foo(a, b=1, /): ... # all positional, b optional

def foo(a, b, /, c, d): ... # a, b positional; c, d required and
either positional or keyword

def foo(a, b, /, c, d=1): ... # a, b positional; c required, d
optional; c, d either positional or keyword

def foo(a, b, /, c, *, d): ... # a, b positional; c required and
either positional or keyword; d required keyword

def foo(a, b=1, /, c=1, *, d=1): ...  # same, but b, c, d optional

That about covers it. But agreed it's no thing of beauty, so let's abandon it.

--Guido van Rossum (python.org/~guido)

More information about the Python-ideas mailing list