[Python-ideas] Short form for keyword arguments and dicts

Andrew Barnert abarnert at yahoo.com
Tue Jun 25 11:14:01 CEST 2013


From: Anders Hovmöller <boxed at killingar.net>
Sent: Monday, June 24, 2013 11:25 PM


Before getting to the specific replies, I'd like to repeat my call for some examples of real (or at least realistic) code that would actually benefit from this change.

I've already agreed that the two special cases of dict construction and str.format could benefit—but those are special cases. Nick Coghlan and others have already suggested they could be better handled with different improvements. Maybe they're wrong; maybe those special cases are important enough, and there is no better solution for them. But you're presenting this as a broader fix than that, and I don't see it. The only other real examples I've seen are my own cases of delegating functions that forward their parameters exactly, and I don't think those need to be improved. 

Maybe there's a lot more to your idea than I and others are seeing. You're clearly a knowledgeable and sane programmer, not some crank, and I believe that you do have real code you'd like to improve. But I can't imagine it, so I'd like you to demonstrate that real code.

>>When the arguments are already variables (parameters or locals) with the same name, you already have the same information, and there is no benefit from getting it twice.
>
>Absolutely not. At that point you have to make a pretty big assumption that this is the case.

An assumption? Sure. A big one? No.

When I'm reading this code:


    url = get_appdir_url(per_user, for_domain, create)

… I have to assume that per_user is some kind of flag value that selects between a per-user appdir and a local-system appdir, not an integer that specifies the primary group ID. Just as I have to assume that get_appdir_url returns a URL to an appdir, not a pandas table full of the populations of world capitals. In other words, I have to assume that whoever wrote the code I'm reading isn't being malicious or psychotic when coming up with names.

And again, this is totally different from the paradigm case for keyword arguments:


    url = get_appdir_url(False, None, True)



Here, maybe I can guess that one of those two boolean values might be a per-user/local-system flag, but I have no idea which one, or whether False means local-system or per-user. So, using keywords makes a _huge_ difference. 

But in the previous case, I always know what per_user means. And, in fact, adding keywords doesn't affect what I have to assume. When I see this:


    url = get_appdir_url(per_user=per_user, for_domain=for_domain, create=create)

… I _still_ have to assume that per_user means what I think it means. It's the same words, with the same meaning. And adding an "=" prefix to each argument wouldn't add any meaning either; it's just a meaningless symbol that I have to pass over to read the actual meaning of the code.

> In order to KNOW you need to go look up the function and compare two lists of names.


No, in order to KNOW I'd need to pore over the implementation of the function, and either prove that it does what I expect, or test it sufficiently to my satisfaction.

Fortunately, I don't usually need that kind of knowledge when reading someone's code. If I want to understand what your script does, or expand its functionality, I read it with the assumption that each expression means what it says. I may come back and look at some of them more carefully if I find a bug, or a clever hack that I don't understand, but that's not the usual case when reading code.

> And if it changes keyword arguments will throw an error upon invocation, positional arguments will not.


How many times has it happened that some function changed the order of its parameters, but didn't change anything else that would break your code? Maybe once or twice in your lifetime as a programmer? Is it really common enough to be worth making your code less readable, even a little bit, to protect against it?

>>Most Python programmers today seem to do a decent job finding the right balance, and the language and library do a decent job helping them. Could that be better? Sure. But encouraging keywords everywhere would not make it better.

>

>Just want to point out that you have no idea of knowing that.

Sure I do. And so do you. If you didn't have some sense, based on experience reading and writing lots of code in Python and other languages, about how well Python programmers take advantage of the freedom to choose between positional and keyword arguments, you wouldn't have proposed a change in the first place.

And this is the key question. You're supporting the general principle that people should use keyword arguments whenever possible—replacing flexibility with TOOWTDI dogma. That can be a good thing when the flexibility has been poorly used (e.g., Python no longer lets you choose whether to explicitly or implicitly decode byte strings), or it can be a bad thing when the flexibility leads to better code. A big part of the reason both you and I use Python is that people have argued out these kinds of questions, instead of just assuming that there's no way of knowing and choosing arbitrarily.

>Except of course the little detail that with my suggestion the added noise would be almost insignificant. 1 extra character per variable name. Only for really horrible code with variable names of 1 or 2 characters will that be a significant increase in "noise". 


I realize this is almost like Godwin's Law here, but…

By the exact same argument, perl sigils are insignificant. But everyone knows they're not. When I see "$remaining = shift(@ARGV);" instead of just "remaining = shift(ARGV);", it disturbs the flow of reading code, despite only being 1 extra character per variable name. That's what people mean when they say it's "ugly"—it's not about typographical beauty, it's about being able to look at code and quickly understand what it's doing.

Consider the fact that Python doesn't require parens around conditions, or that it does require colons in block-introducing statements. Those are even tinier—one characters for the whole statement—and yet they make a huge difference in readability.

There's always a cost in adding extra noise, and just saying "It's not that bad" isn't a good argument. The question is whether the benefit outweighs the cost. The **kw syntax is a stumbling block that every immigrant from JavaScript or C++ runs into at some point—first they have to figure out what it means, then they have to get used to it. But it's so hugely useful that the cost is obviously worth taking. Your =keyword syntax would have the same cost. Would it have a similarly large benefit?


More information about the Python-ideas mailing list