On Jul 27, 2019, at 12:47, Anders Hovmöller firstname.lastname@example.org wrote:
On 27 Jul 2019, at 21:10, Andrew Barnert email@example.com wrote:
Many of the compelling examples for PEP 570 are good examples here. The following are all impossible intentionally, and for different reasons:
skipper = partial(range, step=n) powbase = partial(pow, mod=base) clscheck = partial(isinstance, class_or_tuple=cls)
Those seem like great cases for changing the standard library to use normal parameters! range and pow are both nicer with keyword arguments imo.
Look at the signatures for range and isinstance: range takes an optional argument on the left (or, if you prefer, it’s an overload of two different signatures), which can’t even be expressed in Python syntax; isinstance takes a class or a tuple of classes in the same parameter, so there’s no good name for it. There are a few other functions just like range, and a bunch like isinstance, and some other classes of functions with different kinds of weird signatures (although pow isn’t one of them).
You could argue that these are just bad designs, but better designs weren’t possible when they were added to Python. For example, anything designed to take 1 or many classes since 2.2 would just use *classes instead of a single argument, but isinstance-style functions predate 2.2, so there was no *args. Changing those existing functions would break a lot of existing code. And if that wasn’t acceptable for 2.2 or even 3.0, it’s probably never going to be acceptable.
Also, even for cases like the OP’s where there’s no semantics reason the argument couldn’t have a keyword, there may still be other reasons. When argclinic was added in PEP 436, it was specifically argued that it shouldn’t be used as an opportunity to phase out positional-only params, in part because for many functions the performance cost of keyword processing outweighs the uncommon potential use of the keywords; IIRC, the OP’s specific method was even one of the core examples. And, as PEP 570 points out, METH_FASTCALL makes that potentially true for pure Python functions as well, to the extent that some other stdlib functions might actually want to lose their keyword args.
Well that sounds pretty terrible to me. I’ve tried to write calls with keywords of many many functions in the standard library because it just isn’t really readable with positional :(
I think many of the functions in the stdlib do get it wrong, for legacy reasons (nobody thought about the tradeoff consciously until the argclinic discussion, and also it was a pain to add keywords in C before argclinic—and many of the functions you use most often date back even farther, to before keywords existing at all), but there is an actual tradeoff, so it shouldn’t be 100% of functions take keywords. The two PEPs both make the case for that.
And nobody’s going to sweep through the stdlib evaluating every function. If you’ve got a group of functions that particularly annoys you, and can make the case that the arg parsing performance isn’t important for that function and the keywords are useful, you can file it on b.p.o. (ideally with a patch) and I’m sure someone will take a look.
Meanwhile, there are going to be functions that take positional arguments, whether for semantic reasons, for performance reasons, or for pure legacy issues. As long as any of those cases exist, the OP’s proposal makes sense, at least to me.