On Mon, Nov 15, 2021 at 4:57 AM Christopher Barker firstname.lastname@example.org wrote:
On Sun, Nov 14, 2021 at 9:51 AM Chris Angelico email@example.com wrote:
Also, it's entirely possible that future versions of Python will have a concept of optional arguments that don't *have* defaults,
As noticed earlier in this thread, it seems it's currently possible to do that with functions written in C. (see bisect in Python 3.8). Sorry to be too lazy to go see how that's done, but as you've been digging into this code I figured you'd already know.
That's technically true, although it would perhaps be more accurate to say that C-implemented functions just accept *args and **kwargs and do the work from there. The signatures exposed in Python code are synthesized.
So how hard would it be to expose that functionality in pure Python? Maybe that's worth pursuing to get around the "no perfect sentinel" problem.
From a technical standpoint? Not actually that difficult, and I effectively implemented that as a side effect of PEP 671. You have to fiddle around with the function's dunders to invoke that behaviour, but it can be done.
From a syntactic standpoint? Here be dragons. Or rather, here be endless bikesheddings.
... try: ... print("Ham is", ham) ... except UnboundLocalError: ... print("Ham wasn't set") ...
spam.__defaults_extra__ = (' ((unset)) ',) spam(42)
Ham is 42
Ham wasn't set
It's a hack (FWIW the value in the tuple is what inspect.signature() will show for the default), but what happens is that there truly isn't a default for that argument now. The problem is, there's no really awesome syntax for it, and an endless array of slightly-okay syntax options, so we could argue this till next millennium :)
I'm not currently pushing for any system of "optional argument with no default", but if PEP 671 is accepted, or at least gets enough interest, it might inspire someone to take parts of it and come up with such a proposal.