@@ -10,7 +10,7 @@ Python-Version: 3.14
1010Abstract
1111========
1212
13- This proposal aims to enhance the `` operator ` ` module by adding a
13+ This proposal aims to enhance the :mod: ` operator ` module by adding a
1414``default `` keyword argument to the ``attrgetter `` and ``itemgetter ``
1515functions. This addition would allow these functions to return a
1616specified default value when the targeted attribute or item is missing,
@@ -48,7 +48,7 @@ value for all cases (more about this below in `Rejected Ideas
4848Specification
4949=============
5050
51- Proposed behaviours :
51+ Proposed behaviors :
5252
5353- **attrgetter **: ``f = attrgetter("name", default=XYZ) `` followed by
5454 ``f(obj) `` would return ``obj.name `` if the attribute exists, else
@@ -67,7 +67,7 @@ No functionality change is incorporated if ``default`` is not used.
6767Examples for attrgetter
6868-----------------------
6969
70- Current behaviour, no changes introduced ::
70+ The current behavior is unchanged ::
7171
7272 >>> class C:
7373 ... class D:
@@ -95,7 +95,7 @@ Current behaviour, no changes introduced::
9595 File "<stdin>", line 1, in <module>
9696 AttributeError: type object 'D' has no attribute 'badname'
9797
98- Using ``default ``::
98+ With this PEP, using the proposed ``default `` keyword ::
9999
100100 >>> attrgetter("D", default="noclass")(C)
101101 <class '__main__.C.D'>
@@ -114,7 +114,7 @@ Using ``default``::
114114Examples for itemgetter
115115-----------------------
116116
117- Current behaviour, no changes introduced ::
117+ The current behavior is unchanged ::
118118
119119 >>> obj = ["foo", "bar", "baz"]
120120 >>> itemgetter(1)(obj)
@@ -131,7 +131,7 @@ Current behaviour, no changes introduced::
131131 IndexError: list index out of range
132132
133133
134- Using ``default ``::
134+ With this PEP, using the proposed ``default `` keyword ::
135135
136136 >>> itemgetter(1, default="XYZ")(obj)
137137 'bar'
@@ -148,33 +148,33 @@ Using ``default``::
148148About Possible Implementations
149149------------------------------
150150
151- For the case of ``attrgetter `` is quite direct: it implies using
152- ``getattr `` catching a possible ``AttributeError ``. So
151+ The implementation of ``attrgetter `` is quite direct: it implies using
152+ ``getattr `` and catching a possible ``AttributeError ``. So
153153``attrgetter("name", default=XYZ)(obj) `` would be like::
154154
155155 try:
156156 value = getattr(obj, "name")
157157 except (TypeError, IndexError, KeyError):
158158 value = XYZ
159159
160- Note we cannot rely on using ``gettattr `` with a default value, as would
160+ Note we cannot rely on using ``getattr `` with a default value, as it would
161161be impossible to distinguish what it returned on each step when an
162162attribute chain is specified (e.g.
163163``attrgetter("foo.bar.baz", default=XYZ) ``).
164164
165- For the case of ``itemgetter `` it's not that easy. The more
166- straightforward way is similar to above, also simple to define and
165+ The implementation for ``itemgetter `` is not that easy. The more
166+ straightforward way is also simple to define and
167167understand: attempting ``__getitem__ `` and catching a possible exception
168- (any of the three indicated in ``__getitem__ `` reference). This way,
168+ (any of the three indicated in ``__getitem__ `` ` reference `_ ). This way,
169169``itemgetter(123, default=XYZ)(obj) `` would be equivalent to::
170170
171171 try:
172172 value = obj[123]
173173 except (TypeError, IndexError, KeyError):
174174 value = XYZ
175175
176- However, this would be not as efficient as we'd want for particular cases,
177- e.g. using dictionaries where particularly good performance is desired . A
176+ However, this would be not as efficient as we'd want for certain cases,
177+ e.g. using dictionaries where better performance is possible . A
178178more complex alternative would be::
179179
180180 if isinstance(obj, dict):
@@ -185,16 +185,16 @@ more complex alternative would be::
185185 except (TypeError, IndexError, KeyError):
186186 value = XYZ
187187
188- Better performance, more complicated to implement and explain. This is
188+ While this provides better performance, it is more complicated to implement and explain. This is
189189the first case in the `Open Issues <PEP 769 Open Issues _>`__ section later.
190190
191191
192192Corner Cases
193193------------
194194
195- Providing a ``default `` option would only work when accessing to the
196- item/attribute would fail in a regular situation . In other words, the
197- object accessed should not handle defaults theirselves .
195+ Providing a ``default `` option would only work when accessing the
196+ item/attribute would fail in the normal case . In other words, the
197+ object accessed should not handle defaults itself .
198198
199199For example, the following would be redundant/confusing because
200200``defaultdict `` will never error out when accessing the item::
@@ -205,8 +205,8 @@ For example, the following would be redundant/confusing because
205205 >>> itemgetter("foo", default=-1)(dd)
206206 0
207207
208- The same applies to any user built object that overloads ``__getitem__ ``
209- or ``__getattr__ `` implementing fallbacks.
208+ The same applies to any user defined object that overloads ``__getitem__ ``
209+ or ``__getattr__ `` implementing its own fallbacks.
210210
211211
212212.. _PEP 769 Rejected Ideas :
@@ -221,30 +221,29 @@ The idea of allowing multiple default values for multiple attributes or
221221items was considered.
222222
223223Two alternatives were discussed, using an iterable that must have the
224- same quantity of items than parameters given to
224+ same quantity of items as parameters given to
225225``attrgetter ``/``itemgetter ``, or using a dictionary with keys matching
226226those names passed to ``attrgetter ``/``itemgetter ``.
227227
228- The really complex thing to solve in these casse, that would make the
229- feature hard to explain and with confusing corners , is what would happen
230- if an iterable or dictionary is the *unique * default desired for all
228+ The really complex thing to solve here (making the
229+ feature hard to explain and with confusing corner cases) , is what would happen
230+ if an iterable or dictionary is the *actual * default desired for all
231231items. For example::
232232
233- >>> itemgetter("a", default=(1, 2)({})
233+ >>> itemgetter("a", default=(1, 2)) ({})
234234 (1, 2)
235235 >>> itemgetter("a", "b", default=(1, 2))({})
236236 ((1, 2), (1, 2))
237237
238238If we allow "multiple default values" using ``default ``, the first case
239- in the example above would raise an exception because more items in the
240- default than names, and the second case would return ``(1, 2)) ``. This is
241- why emerged the possibility of using a different name for multiple
242- defaults (``defaults ``, which is expressive but maybe error prone because
243- too similar to ``default ``).
239+ in the example above would raise an exception because there are more items
240+ than names in the default , and the second case would return ``(1, 2)) ``. This is
241+ why we considered the possibility of using a different name for multiple
242+ defaults (e.g. ``defaults ``, which is expressive but maybe error prone because
243+ it is too similar to ``default ``).
244244
245- As part of this conversation there was another proposal that would enable
246- multiple defaults, which is allowing combinations of ``attrgetter `` and
247- ``itemgetter ``, e.g.::
245+ Another proposal that would enable multiple defaults, is allowing
246+ combinations of ``attrgetter `` and ``itemgetter ``, e.g.::
248247
249248 >>> ig_a = itemgetter("a", default=1)
250249 >>> ig_b = itemgetter("b", default=2)
@@ -254,20 +253,20 @@ multiple defaults, which is allowing combinations of ``attrgetter`` and
254253 >>> ig_combined({})
255254 (1, 2)
256255
257- However, combining ``itemgetter `` or ``attrgetter `` is a totally new
258- behaviour very complex to define, not impossible, but beyond the scope of
256+ However, combining ``itemgetter `` or ``attrgetter `` is totally new
257+ behavior and very complex to define. While not impossible, it is beyond the scope of
259258this PEP.
260259
261- At the end having multiple default values was deemed overly complex and
260+ In the end, having multiple default values was deemed overly complex and
262261potentially confusing, and a single ``default `` parameter was favored for
263262simplicity and predictability.
264263
265264
266265Tuple Return Consistency
267266------------------------
268267
269- Another rejected proposal was adding a flag to always return tuple
270- regardless of how many keys/names/indices were sourced to arguments .
268+ Another rejected proposal was adding a flag to always return a tuple
269+ regardless of how many keys/names/indices were given .
271270E.g.::
272271
273272 >>> letters = ["a", "b", "c"]
@@ -276,8 +275,8 @@ E.g.::
276275 >>> itemgetter(1, 2, return_tuple=True)(letters)
277276 ('b', 'c')
278277
279- This would be of a little help for multiple default values consistency,
280- but requires further discussion and for sure is out of the scope of this
278+ This would be of little help for multiple default values consistency,
279+ requiring further discussion, and is out of the scope of this
281280PEP.
282281
283282
@@ -286,39 +285,39 @@ PEP.
286285Open Issues
287286===========
288287
289- Behaviour Equivalence for ``itemgetter ``
290- ----------------------------------------
288+ Behavior Equivalence for ``itemgetter ``
289+ ---------------------------------------
291290
292- We need to define how ``itemgetter `` would behave, if just attempt to
293- access the item and capture exceptions no matter which the object, or
294- validate first if the object provides a ``get `` method and use it to
295- retrieve the item with a default. See examples in the `About Possible
291+ For ``itemgetter ``, should it just attempt to
292+ access the item and capture exceptions regardless of the object's API , or
293+ should it first validate that the object provides a ``get `` method, and if so use it to
294+ retrieve the item with a default? See examples in the `About Possible
296295Implementations <PEP 769 About Possible Implementations_> `__ subsection
297296above.
298297
299298This would help performance for the case of dictionaries, but would make
300299the ``default `` feature somewhat more difficult to explain, and a little
301- confusing if some object that is not a dictionary but provides a ``get ``
302- method is used . Alternatively, we could call ``.get `` *only * if the
300+ confusing if some object that is not a dictionary but still provides a ``get ``
301+ method. Alternatively, we could call ``.get `` *only * if the
303302object is an instance of ``dict ``.
304303
305- In any case, a desirable situation is that we do *not * affect performance
304+ In any case, it is desirable that we do *not * affect performance
306305at all if the ``default `` is not triggered. Checking for ``.get `` would
307- get the default faster in case of dicts, but implies doing a verification
308- in all cases. Using the try/except model would make it not as fast as it
309- could in the case of dictionaries, but would not introduce delays if the
306+ be faster for dicts, but implies doing a verification
307+ in all cases. Using the try/except model would make it less efficient as possible
308+ in the case of dictionaries, but only if the
310309default is not triggered.
311310
312311
313312Add a Default to ``getitem ``
314313----------------------------
315314
316- It was proposed that we could also enhance ``getitem ``, as part of the of
317- this PEP, adding ``default `` also to it .
315+ It was proposed that we could also enhance ``getitem ``, as part of
316+ this PEP, adding the ``default `` keyword to that function as well .
318317
319318This will not only improve ``getitem `` itself, but we would also gain
320319internal consistency in the ``operator `` module and in comparison with
321- the ``getattr `` builtin function that also has a default.
320+ the ``getattr `` builtin function, which also has a default.
322321
323322The definition could be as simple as the try/except proposed above, so
324323doing ``getitem(obj, name, default) `` would be equivalent to::
@@ -328,15 +327,15 @@ doing ``getitem(obj, name, default)`` would be equivalent to::
328327 except (TypeError, IndexError, KeyError):
329328 result = default
330329
331- (However see previous open issue about special case for dictionaries)
330+ (However see previous open issue about special case for dictionaries. )
332331
333332
334333How to Teach This
335334=================
336335
337- As the basic behaviour is not modified, this new ``default `` can be
336+ As the basic behavior is not modified, this new ``default `` can be
338337avoided when teaching ``attrgetter `` and ``itemgetter `` for the first
339- time, and can be introduced only when the functionality need arises .
338+ time. It can be introduced only when the functionality is needed .
340339
341340
342341Backwards Compatibility
@@ -355,6 +354,8 @@ Security Implications
355354Introducing a ``default `` parameter does not inherently introduce
356355security vulnerabilities.
357356
357+ .. _reference : https://docs.python.org/3/reference/datamodel.html#object.__getitem__
358+ .. _module : https://docs.python.org/3/library/operator.html
358359
359360Copyright
360361=========
0 commit comments