Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions peps/pep-0769.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ The implementation of ``attrgetter`` is quite direct: it implies using

try:
value = getattr(obj, "name")
except (TypeError, IndexError, KeyError):
except (IndexError, KeyError):
value = XYZ

Note we cannot rely on using ``getattr`` with a default value, as it would
Expand All @@ -200,35 +200,41 @@ attribute chain is specified (e.g.
The implementation for ``itemgetter`` and ``getitem`` is not that
easy. The more straightforward way is also simple to define and
understand: attempting ``__getitem__`` and catching a possible
exception (any of the three indicated in ``__getitem__`` `reference`_).
This way, ``itemgetter(123, default=XYZ)(obj)`` or
``getitem(obj, 123, default=XYZ)`` would be equivalent to::
exception (see below). This way, ``itemgetter(123, default=XYZ)(obj)``
or ``getitem(obj, 123, default=XYZ)`` would be equivalent to::

try:
value = obj[123]
except (TypeError, IndexError, KeyError):
except (IndexError, KeyError):
value = XYZ

However, for performance reasons the implementation may look more
like the following, which has the same exact behaviour::
like the following, which has the same exact behavior::

if type(obj) == dict:
value = obj.get(123, XYZ)
else:
try:
value = obj[123]
except (TypeError, IndexError, KeyError):
except (IndexError, KeyError):
value = XYZ

Note how the verification is about the exact type and not using
``isinstance``; this is to ensure the exact behaviour, which would be
``isinstance``; this is to ensure the exact behavior, which would be
impossible if the object is a user defined one that inherits ``dict``
but overwrites ``get`` (similar reason to not check if the object has
a ``get`` method).

This way, performance is better but it's just an implementation detail,
so we can keep the original explanation on how it behaves.

Regarding the exception to be captured, even if ``__getitem__``
can raise ``IndexError``, ``KeyError``, or ``TypeError`` (see its
`reference`_), 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.


Corner Cases
------------
Expand Down