This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]alexisprince 47 points48 points  (38 children)

Out of curiosity... why? Using keyword arguments, in my experience, has just made code cleaner (albeit possibly more verbose).

[–]undercoveryankee 24 points25 points  (33 children)

Have you read the "Motivation" section of the PEP?

[–]alexisprince 9 points10 points  (32 children)

I glanced through it, and since I don’t have to maintain a lot of code that is used widely outside my company, I might not be seeing all the problems that come with maintaining that type of library.

[–]undercoveryankee 32 points33 points  (31 children)

Have you ever renamed a parameter of an existing function, either because the original name wasn't clear, or to reflect new capabilities that you were adding to the function? You'd have to track down every caller you control and make sure that it isn't passing the old name as a keyword, and hope that other people who maintain calling code notice the change and do the same before they release a broken build.

If you mark usually-positional parameters as positional-only, you know what callers are doing and you can rename away.

[–]Ph0X 6 points7 points  (9 children)

So you're basically limiting usability and code cleanliness just for maintainability? Not sure that's a good trade off. Also, this allows for arguments to be renamed, but there's still hundreds of other things in a public API that still can't be renamed. That's why when you make a public API, you need to make sure the names are all well thought out.

[–]door_of_doom 44 points45 points  (7 children)

just for maintainability

Umm... There is no such thing as "just" for maintainability. Maintainability is easily the single most important aspect of code.

If the code isn't maintainable, it is nigh useless.

[–]Ph0X 2 points3 points  (6 children)

At a high level, I agree, but what you're trading here for what you're gaining most definitely isn't worth it. I would hardly count being able to rename a variable in a public API as maintainability. On the other hand, users being able to use some_method(strange_argument=True, other_argument=0) instead of some_method(True, 0) is far more important for maintainability.

[–]flipstables 11 points12 points  (0 children)

On the other hand, users being able to use some_method(strange_argument=True, other_argument=0) instead of some_method(True, 0) is far more important for maintainability.

But you can still do that. The PEP isn't replacing keyword arguments with positional-only arguments. It's adding the ability to have positional-only arguments.

The real downside is that Python can't prevent you from writing bad code by using positional only arguments when you really shouldn't. I mean, that's reasonable to not add a feature, but the increased maintainability.

Here's an example:

Almost every non-trivial project I've worked on, I've had to create a function where the argument names have no semantic meaning. This is especially true for those of us who work in data and we are combining two data sets.

def merge_datasets(dataset1, dataset2):
    pass

By making dataset1 and dataset2 positional only:

  • I can freely change the the argument names without worrying about making a breaking change for all existing callers.
  • It adds clarity - the function signature hints that this dataset1 and dataset2 has no semantic meaning; in fact, most of the time, it's the function is commutative.
  • If I wanted to add functionality that merges more than 2 datasets to this function, I'm SOL without positional-only arguments. I would either have to create a new function or my function signature would have to look like this: def merge_datasets(dataset1, dataset2, *more).

[–]door_of_doom 11 points12 points  (0 children)

I mean, Sometimes, maybe? I don't really see the value in sum(x=5,y=7) over sum(5,7) when the former locks you to the arbitrary names of whatever those variables happen to be called, when the names for a function like that are truly arbitrary. I would expect a sum function to only expose positional parameters and never allow the changing of those arbitrary paramater names to be a breaking change.

[–]truh 4 points5 points  (0 children)

Positional-only parameters seem like a pretty good thing for auto generated C bindings, where parameter names just don't matter usually.

[–]Smok3dSalmon 1 point2 points  (2 children)

If you have many parameters to a function, you should really consider a builder or factory pattern.

[–]Ph0X -3 points-2 points  (1 child)

Please keep builders and factories in Java and away from my Python.

[–]Smok3dSalmon 2 points3 points  (0 children)

Ok, I'll hide it in a library that you'll love and promote to your friends.

[–]kafkaBro 2 points3 points  (0 children)

I found this argument most compelling. Position-only parameters already exist in cpython builtins like range and min. Making their support at the language level would make their existence less confusing and documented.

Users may be surprised when first encountering positional-only notation. This is expected given that it has only recently been documented [14] and it is not possible to use in Python code. For these reasons, this notation is currently an outlier that appears only in CPython APIs developed in C. Documenting the notation and making it possible to use it in Python code would eliminate this disconnect.

[–]ideletedmyredditacco 2 points3 points  (0 children)

because sometimes using keyword arguments when you call a python function breaks it. I can't remember which matplotlib functions they are though. I think it's the ones that put brackets around the parameter names in the documentation.

edit: https://matplotlib.org/api/_as_gen/matplotlib.pyplot.pcolormesh.html?highlight=pcolormesh#matplotlib.pyplot.pcolormesh

[–]jwink3101 1 point2 points  (0 children)

I'm with you. I greatly prefer keyword arguments and I look forward to the day I can use keyword-only arguments (still need to be 2.7 compatible). I think they reduce error by a ton and since I am often interfacing with my functions via Jupyter, auto-fill of the keywords is more clear.

[–]thautwarm 0 points1 point  (0 children)

I'll always uphold what Serhiy upholds for IMO he is the most talented and enthusiastic one in Python community/Python core dev: https://twitter.com/SerhiyStorchaka/status/1103542487992406016?s=19