Issue 4124: Patch for adding "default" to itemgetter and attrgetter (original) (raw)

Created on 2008-10-14 22:07 by tebeka, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
getter.patch tebeka,2008-10-14 22:07 Code path
Messages (7)
msg74774 - (view) Author: Miki Tebeka (tebeka) * Date: 2008-10-14 22:07
This is a patch for adding "default" keyword to itemgetter and attrgetter. This way you can do: >>> f = itemgetter(0, default=1) >>> f([]) 1 >>> f= attrgetter("a", default="b") >>> f(object()) 'b' >>> I'm not sure about all the Py_INCREF I've placed there, someone with more knowledge than me should review the code.
msg80839 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-01-30 22:22
Will take a look at it next week.
msg80840 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-01-30 22:50
Am curious about your use cases. ISTM that in every case I've every used either function, I've always known that the attribute or item is going to be there. For instance, the original motivating use cases were to support the key= argument to min/max/sorted/nlargest/nsmallest/groupby and to support iterator algebra with itertools: def powerset(iterable): '''Iterate over all subsets. >>> list(powerset('abc')) [set([]), set(['a']), set(['b']), set(['a', 'b'])] ''' # Only 1 initial call to PyObject_Hash(). # No trips around the eval-loop. # Memory friendly. seq = map(set, list(iterable)[::-1]) selector_stream = product([False, True], repeat=len(seq)) newsets, ns1 = tee(starmap(set, repeat(()))) components = imap(compress, repeat(seq), selector_stream) sets_and_components = imap(chain, izip(newsets), components) results = starmap(set.update, sets_and_components) return imap(itemgetter(0), izip(ns1, results))
msg81028 - (view) Author: Miki Tebeka (tebeka) * Date: 2009-02-03 06:47
Hmmm, too much time has passed and my 1bit memory has overflowed since :) IIRC it has to do with the fact that not all nodes in BeautifulSoup has a "name" attribute. I wanted to count how may "tr" there were, so len(filter(lambda n: n == "tr", map(attrgetter("name"), soup))) was what I wanted to do, but I got AttributeError. The natural way to me would be len(filter(lambda n: n == "tr", map(attrgetter("name", ""), soup))) but instead I had to do len(filter(lambda n: n == "tr", map(lambda n: gettattr(n, "name", ""), soup))) Another thing I can think of is for usage in count/max ... when some of the objects don't have the attribute you're looking for and it's by design (bad one maybe). You'd like to be able to do: max(map(itemgetter("time", 0)), articles)
msg81095 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-02-03 20:28
That makes sense. You've found two object models that have optional attributes and have had some need to extract them with a default. My remaining concern is about adding complexity for functionality that is not often needed. It wouldn't be an issue if itemgetter() and attrgetter() already had a simple signature, but they already allow multiple arguments and IMO that doesn't mesh well with providing defaults. FWIW, looking back at your use cases, it feels like the functional tools have come together awkwardly. It may be slower, but the following seems easier to read, easier to write, and clearer about its intention: sum('tr' == getattr(node, 'name', '') for node in soup) max(getattr(art, 'time', 0) for art in articles) In general, listcomps and genexps read better than equivalents using lambda or a stack of builtin operators. And, lambda is dog slow. So, the following may be slower than the above code: len(filter(lambda n: n == "tr", map(attrgetter("name", ""), soup)))
msg81096 - (view) Author: Miki Tebeka (tebeka) * Date: 2009-02-03 20:37
Can't we find a faster dog for lambda :) Anyway, I agree that we need to see more demand for that before going on. Let's keep this ticket open and see if someone else comes along.
msg85096 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-04-01 21:14
Am closing this one because the API doesn't mesh well with the existing extensions for multiple attributes. If those weren't already present, there might be a case for adding this extension.
History
Date User Action Args
2022-04-11 14:56:40 admin set github: 48374
2009-04-01 21:14:25 rhettinger set status: open -> closedresolution: rejectedmessages: +
2009-02-04 20:13:58 rhettinger set priority: low
2009-02-03 20:37:48 tebeka set messages: +
2009-02-03 20:28:51 rhettinger set messages: +
2009-02-03 06:47:21 tebeka set messages: +
2009-01-30 22:50:36 rhettinger set messages: +
2009-01-30 22:22:19 rhettinger set assignee: rhettingertype: enhancementmessages: + nosy: + rhettinger
2008-10-14 22:07:33 tebeka create