[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?
No.
> 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
code-smell.
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.
--
Steve
More information about the Python-ideas
mailing list