Should TypeError be caught and silenced by itemgetter/getitem with a default? I believe it shouldn’t.
Whereas KeyError and IndexError do signal that the container does not contain the specified key or index (which is an expected condition, given that you bothered to specify a default), TypeError is likely to signal a bug in your code… It may be a problem with the type of a key/index, but it may also be the case that the object the getter callable is passed to is not a container at all (e.g., when getitem(123, 'key', 'default') is attempted).
Moreover, IMHO, the semantics of itemgetter/getitem with a default should resemble the semantics of dict.get(). And please note that the latter does raiseTypeError when a wrong (in this case: unhashable) type of a key in encountered:
>>> {}.get([])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Thanks! So if default is an optional argument (in the sense that the user does not need to provide it) how do you internally tell the difference between the case where the user does not pass in a value ( in which case you need to raise if they attribute does not exist) and the case I mentioned above, where we we want a return the value of None? Both cases look the same to the callee unless attrgetter uses a special sentinel value.
As mentioned, this is a problem that already exists in other spaces, and I don’t think this PEP is attempting to solve it. A different PEP that introduces sentinels, like PEP 661, will make that case easier.
Trying to solve two separate problems in one PEP is too challenging.
The implementation could use a sentinel (e.g. object()), not None to determine if the default keyword argument was given. It’s an implementation detail, not a problem at all.
@zuo@dg-pb you’re right! I just improved the PEP with this paragraph in the “About Possible Implementations” section:
Regarding the exception to be captured, even if ``__getitem__``
`reference`_ can raise ``IndexError``, ``KeyError``, or ``TypeError``,
only the first two can happen if the container does not contain the
indicated key or index, and the latter is likely to signal a bug in the
code, so we're not capturing it to trigger the default behavior.
Thank you for your work on this PEP, I believe the proposal will we a useful enhancement to the stuff provided by the operator module!
One minor editorial mistake I see in the current text of the PEP: in the code snippet focused on attrgetter() near the beginning of the About Possible Implementations section, the exception being caught should be AttributeError rather than (IndexError, KeyError).
First of all, the Python Steering Council would like to thank Facundo Batista for the work on PEP 769. We appreciate the effort put into crafting this proposal and the thoughtful discussions it generated in the community. Adding default handling to these operator functions was well-articulated and considered.
After careful review, however, the Python Steering Council has rejected PEP 769 (Add a ‘default’ keyword argument to ‘attrgetter’, ‘itemgetter’ and ‘getitem’). While the proposal is well-written and the concept of adding default handling to these operator functions was clearly articulated, we have several concerns and we believe there is insufficient motivation for this addition to the standard library. We believe that the proposal would benefit from more evidence that this feature addresses a widespread need in the Python ecosystem and why it specifically needs to be in the standard library rather than a third-party package. It’s not clear to us how this change would improve Python codebases, including the standard library itself, and more usage examples would help show the potential benefits. Without this information, it’s hard to justify expanding these well-established functions.
We also believe that the proposed functionality adds some complexity, especially with dotted attribute paths and potential corner cases that could confuse users. The design challenges, some of which were mentioned in the PEP’s rejected alternatives section, show the feature is more complicated than it first appears, and we don’t believe we have enough evidence that the suggested path is a clear win. This was also apparent in the discussion thread, with suggestions for callable defaults, special handling of exceptions, and sentinel values for implementation. The interactions with objects that already handle missing attributes or items in their ways further complicates the behavior.
We recommend implementing this as a third-party package on PyPI to test the design in real-world scenarios, collect usage data and patterns, and allow the community to experiment with the API and provide feedback. The operator module is a fundamental part of Python, and changes to it warrant thorough vetting through practical application. If future evidence demonstrates significant adoption and clear benefits that cannot be adequately provided by a third-party package, the Steering Council would welcome a revised proposal with stronger justification.
Pablo, in representation of the Python Steering Council