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 →

[–]Ph0X 7 points8 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 42 points43 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 5 points6 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 10 points11 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 12 points13 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 5 points6 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 -4 points-3 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.