[Python-ideas] Keyword only argument on function call

Steven D'Aprano steve at pearwood.info
Thu Sep 6 09:10:28 EDT 2018

On Thu, Sep 06, 2018 at 12:15:46PM +0200, Anders Hovmöller wrote:

> I have a working implementation for a new syntax which would make 
> using keyword arguments a lot nicer. Wouldn't it be awesome if instead 
> of:
> 	foo(a=a, b=b, c=c, d=3, e=e)
> we could just write:
> 	foo(*, a, b, c, d=3, e)
> and it would mean the exact same thing?


> This would not just be shorter but would create an incentive for
> consistent naming across the code base. 

You say that as if consistent naming is *in and of itself* a good thing, 
merely because it is consistent.

I'm in favour of consistent naming when it helps the code, when the 
names are clear and relevant. But why should I feel bad about failing to 
use the same names as the functions I call? If some library author names 
the parameter to a function "a", why should I be encouraged to use 
that same name *just for the sake of consistency*?

> So the idea is to generalize the * keyword only marker from function 
> to also have the same meaning at the call site: everything after * is 
> a kwarg. With this feature we can now simplify keyword arguments 
> making them more readable and concise. (This syntax does not conflict 
> with existing Python code.)

It's certainly more concise, provided those named variables already 
exist, but how often does that happen? You say 30% in your code base.

(By the way, well done for writing an analysis tool! I mean it, I'm not 
being sarcastic. We should have more of those.)

I disagree that f(*, page) is more readable than an explicit named 
keyword argument f(page=page).

My own feeling is that this feature would encourage what I consider a 
code-smell: function calls requiring large numbers of arguments. Your 
argument about being concise makes a certain amount of sense if you are 
frequently making calls like this:

# chosing a real function, not a made-up example
open(file, mode=mode, buffering=buffering, encoding=encoding, 
     errors=errors, newline=newline, closefd=closefd, opener=opener)

If 30% of your function calls look like that, I consider it a 

The benefit is a lot smaller if your function calls look more like this:

open(file, encoding=encoding)

and even less here:

open(file, 'r', encoding=self.encoding or self.default_encoding, 
     errors=self.errors or self.default_error_handler)

for example. To get benefit from your syntax, I would need to 
extract out the arguments into temporary variables:

encoding = self.encoding or self.default_encoding
errors = self.errors or self.default_error_handler
open(file, 'r', *, encoding, errors)

which completely cancels out the "conciseness" argument.

    First version, with in-place arguments:
        1 statement
        2 lines
        120 characters including whitespace

    Second version, with temporary variables:
        3 statements
        3 lines
        138 characters including whitespace

However you look at it, it's longer and less concise if you have to 
create temporary variables to make use of this feature.


More information about the Python-ideas mailing list