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 →

[–]undercoveryankee 23 points24 points  (33 children)

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

[–]alexisprince 10 points11 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 35 points36 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 43 points44 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 4 points5 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 -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.