
On Wed, Oct 27, 2021 at 2:30 PM Ethan Furman <ethan@stoneleaf.us> wrote:
On 10/23/21 5:13 PM, Chris Angelico wrote:
PEP: 671 Title: Syntax for late-bound function argument defaults
I have a major concern about the utility of this addition -- it was mentioned already (sorry, I don't remember who) and I don't think it has yet been addressed.
Using the `bisect()` function as a stand-in for the 20+ years worth of Python APIs in existence:
def bisect_right(a, x, lo=0, hi=None, *, key=None): if hi is None: hi = len(a) while lo < hi: ...
That function would be transformed to:
def bisect_right(a, x, lo=0, @hi=len(a), *, key=None): if hi is None: hi = len(a) while lo < hi: ...
Notice that the `None` check is still in the body -- why? Backwards compatibility: there is code out there that actually passes in `None` for `hi`, and removing the None-check in the body will suddenly cause TypeErrors.
This seems like a lot of effort for a very marginal gain.
The question then becomes: How important is this feature of being able to pass None as a stand-in for the length of the list? If it's important, then don't change the style of the code at all. But since help(bisect) clearly states that the default is len(a), and doesn't say anything about passing None, so it would be just as valid to deem such code to be buggy. Obviously that decision has to be made individually for each use-case, but one thing is clear: newly-defined APIs will not need to have None-pollution in this way. Also, anything that uses a dedicated sentinel should be safe to convert; consider: # Inspired by socket.create_connection, but simplified: _USE_GLOBAL_DEFAULT = object() def connect(timeout=_USE_GLOBAL_DEFAULT): if timeout is _USE_GLOBAL_DEFAULT: timeout = default_timeout If any outside caller is reaching into the module and referring to this underscore-preceded name, it is buggy, and I would have no qualms in breaking that code. (The inspiration for this can't actually be converted, since socket.create_connection with the global default just doesn't call the settimeout() method, but there will be other cases where the same applies.) As with every new feature, a decision has to be made as to whether old code should be changed. This is no different, but I do believe that in many cases, it will be safe to do so. ChrisA