This is not an errata but rather a suggestion for an addition to Item 24.
Sometimes you cannot use None as the default value for a keyword argument because None is a valid value that the caller may specify. In that case, one can do something like the following:
from datetime import datetime
sentinel = object()
def log(message, when=sentinel):
"""Log a message with or without a timestamp.
Args:
message: Message to print.
when: datetime of when the message occurred.
Defaults to the present time.
if when is None, the message is logged without a timestamp.
"""
if when is None:
print(f'{message}')
else:
if when is sentinel:
when = datetime.now()
print(f'{when}: {message}')
>>> log('Hi there!') # log with current time
2020-06-11 16:41:28.401196: Hi there!
>>> log('Hi there!', datetime(2020, 1, 1, 0, 0)) # log with specified time
2020-01-01 00:00:00: Hi there!
>>> log('Hi there!', None) # log without a time
Hi there!
>>>
This extension to item 24 example 2 allows the caller to specify None for when in order to suppress the timestamp, perhaps for a message that is not associated with any particular time.
This is kind of a silly example, I'm sure you can come up with a better use case where you might want to have an argument with a default that could be None, but I think it would be helpful to explain how to deal with that situation as part of this Item.
Thank you for the suggestion! Sorry for my long delay. Yes, a sentinel will work if None is somehow significant like this. But generally I'd avoid defining an API like that if possible.
This is not an errata but rather a suggestion for an addition to Item 24.
Sometimes you cannot use None as the default value for a keyword argument because None is a valid value that the caller may specify. In that case, one can do something like the following:
This extension to item 24 example 2 allows the caller to specify None for when in order to suppress the timestamp, perhaps for a message that is not associated with any particular time.
This is kind of a silly example, I'm sure you can come up with a better use case where you might want to have an argument with a default that could be None, but I think it would be helpful to explain how to deal with that situation as part of this Item.