Syntactic sugar to encourage use of named arguments

Issue

Named arguments confer many benefits by promoting explicit is better than implicit, thus increasing readability and minimising the risk of inadvertent transposition. However, the syntax can become needlessly repetitive and verbose.

Consider the following call:

my_function(
  my_first_variable=my_first_variable,
  my_second_variable=my_second_variable,
  my_third_variable=my_third_variable,
)

The verbosity and redundancy discourages use of named arguments (and therefore, their benefits) and reduces readability by increasing noise. I have personally encountered this many times.

Proposition

I would like to propose a simple syntactic sugar in the case that the name of the variable provided as the argument value is the same as the name of the argument itself.

my_function(=my_first_variable, =my_second_variable, =my_third_variable)

Benefits

  • Encourages use of named variables, thereby increasing readability (explicit is better than implicit) and reducing bugs from argument transposition
  • Reduces verbosity (readability counts)
  • Encourages authors to use the same variable name when calling a function as the argument (increases consistency of variable names used, thereby increasing readability)
  • Reminiscent of python’s long-standing *args and **kwargs syntax (established pythonic style)
  • Reminiscent of python’s existing f-string debug f'{var=}' syntax (established pythonic style) and with a very similar function
  • This should be relatively easy to implement as it is simple syntactic sugar (if the implementation is easy to explain, it may be a good idea)
  • Backwards compatibility: this change is fully backwards compatible since the proposed syntax would raise a syntax error in current python versions
25 Likes

There are some discussions about this idea, but there was no consensus/conclusion:

6 Likes

I think that having the equal sign at the end of the variable func(a=) may ease the implementation and be more intuitive because you already have a similar syntax for f strings:
f"{x=}"

17 Likes

Ruby has this feature: foo(x:, y:) is syntax sugar for foo(x: x, y: y).

I think I maybe prefer the equal sign at the beginning, but it’s more consistent with the Python 3.8 format string syntax if it’s at the end.

Here is more prior discussion:

https://mail.python.org/archives/list/python-ideas@python.org/thread/SIMIOC7OW6QKLJOTHJJVNNBDSXDE2SGV/

4 Likes

I don’t know what the SC will think of this proposal, and I don’t have time to do a lot of mentoring in this area, but if a few folks here will come together and submit a PEP (following the process from PEP 1) and you need a sponsor you can put my name in. I personally prefer the syntax foo(x=, y=).

27 Likes

I can help out as needed. Who wants to champion the proposal and write up the PEP?

5 Likes

I’d be very happy to write up the PEP

4 Likes

I’ll get started on this now. Thank you Guido and Chris.

6 Likes

I would be interested in helping as well.

3 Likes

Great to see this feature being discussed again after so many years, signals that its value is sound. I would be happy to contribute.

3 Likes

Fantastic, thanks so much both! I’m going to research this a little more and think about how a draft will look but will certainly follow up

1 Like

This might help: PEP 12 – Sample reStructuredText PEP Template | peps.python.org

1 Like

I think the arguments presented this time around are the most motivating (at least to me). In particular, I like this one: “Encourages authors to use the same variable name when calling a function as the argument”. That’s something I will intentionally fix if argument names drift apart. In my opinion, it is beneficial to have syntax that induces coders to do this.

I don’t think this argument was suggested the last couple times this was proposed.

2 Likes

Can the PEP have a recommendation for static analysis tools (like mypy) catch if this is used but the corresponding variable of the same name doesn’t exist?

3 Likes

Yes, definitely…

… though I suspect that this is nothing more than a plain vanilla NameError. Am I understanding you correctly, and you mean code like this?

def spam():
    x = 1234 # no y
    func(x=x, y=y)
    func(x=, y=) # or func(=x, =y) if that's the chosen syntax

If so, it should be no different from the longhand line above it, or any other attempt to reference a variable that doesn’t exist. Obviously static analysis tools will have to be taught about the new syntax, but that’s the case for all syntax.

Or were there other recommendations you had in mind?

1 Like

Yep that’s the main thing I had in mind. I figure if nested, it wouldn’t be caught at import time, but static analysis could warn on it.

1 Like

Yeah, there’s definitely value in catching this sort of thing statically. I’ve no idea which checkers report on this (I gave MyPy a quick whirl and it didn’t report it, but that’s with default settings so maybe that can be turned on), but regardless, it should be able to be reported on regardless of this particular piece of syntax.

3 Likes

Mypy can do that check, but it’s disabled by default. Probably because it’s rather tricky to catch all the situations correctly, so it’s likely that you’ll get false positives.

3 Likes

I think I prefer param= over the equals sign on the other side. My editor (vscode) already would be happy to autocomplete this since it lets me tab complete var=

Like in a day at work, I already saw multiple times that I would use this functionality.

So cool!

4 Likes

I would use it all the time, it would debulk a lot of code that I read, but Python already has too much stuff.

On the balance, I am weakly in favour of this, with the key= syntax.

4 Likes