On 4 Dec 2021, at 21:21, Chris Angelico <rosuav@gmail.com> wrote:

On Sun, Dec 5, 2021 at 5:29 AM Barry Scott <barry@barrys-emacs.org> wrote:



On 1 Dec 2021, at 06:16, Chris Angelico <rosuav@gmail.com> wrote:

I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
with some additional information about the reference implementation,
and some clarifications elsewhere.

(I suspect that there was a reply that I should be replying to but, cannot find one appropriate)

I have a lot of code that exploits the fact that passing an explicit None will cause the early bound default idiom to set the default for me.

def inner(timestamp=None):
       if timestamp is None:
               timestamp = time.time()
       do_stuff...

def outer(timestamp=None):
       inner(timestamp=timestamp)

outer can in an idiomatic way have inner default timestamp and not have to know what that means.

If you need outer() to be able to have a value that means "use the
default", then there are three options:

1) Don't pass timestamp at all. In simple cases where it will only and
always specify the default, this is fine.
2) Define a sentinel that is indeed part of your API.
3) Use *args or **kwargs to choose whether to pass it or not (best if
there are multiple of them).

You can continue to use the existing system of "if none, do this", or
you can flip it around and have the sentinel as a special token within
your code:

def inner(timestamp=>time.time()):
   if timestamp is None: timestamp = time.time()

And, obviously, if you end up needing the write the explicit check for None there is no
advantage to using late bound default.


Depends on how important this feature is outside of your own helper
functions. (I would probably not do this for None specifically - if
it's purely internal, I'm more likely to use a dedicated local
sentinel object.)

But as soon as there are two or three arguments that "might have to be
passed, might not", it's far more readable to use kwargs to pass just
the ones you want.

def outer(**kwargs):
   inner(**kwargs)

That way, if something changes in inner(), you don't have to worry
about breaking your caller's API.

Yes that's a good point. Use the *kwargs style to pass down stuff.


With late bound I cannot do this without more complex pattern of building an arg list.

What if passing None still worked? I know the argument that there are more sentinels then None.

def inner(timestamp=>time.time())
       do_stuff...

def outer(timestamp=None):
       inner(timestamp=timestamp)

The code in inner that decides to when to allow the default could check for timestamp being
missing or arg present and None.

Would the lack of support for other sentinels out weight the simple way to get the default applied?


None is most assuredly not going to trigger a late-bound default.

Are you state that this is because in most of the cases where I might think that I need this behaviour there are better patterns to use like *kwargs?
Is that worth stating in the PEP in the rejected ideas?

Python is not JavaScript :)

Thank your choice of deity for that!

Barry


ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/QWYXRITR56CKURYKE7CKQ7A4WVNTUVJL/
Code of Conduct: http://python.org/psf/codeofconduct/