itemgetter with default arguments

Antoon Pardon antoon.pardon at vub.be
Fri May 4 09:27:16 EDT 2018


On 04-05-18 15:01, Steven D'Aprano wrote:
> A re-occurring feature request is to add a default to itemgetter and 
> attrgetter. For example, we might say:
>
> from operator import itemgetter
> f = itemgetter(1, 6, default="spam")  # proposed feature
> f("Hello World!")  # returns ('e', 'W')
> f("Hello")         # returns ('e', 'spam')
>
>
> Two senior developers have rejected this feature, saying that we should 
> just use a lambda instead.
>
> I might be slow today, but I cannot see how to write a clear, obvious, 
> efficient lambda that provides functionality equivalent to itemgetter 
> with a default value.
>
> Putting aside the case where itemgetter takes multiple indexes, how about 
> the single index case? How could we get that functionality using a lambda 
> which is simple and obvious enough to use on the fly as needed, and 
> reasonably efficient?
>
> Here are the specifications:
>
> * you must use lambda, not def;
>
> * the lambda must take a single function, the sequence you want to
>   extract an item from;
>
> * you can hard-code the index in the body of the lambda;
>
> * you can hard-code the default value in the body of the lambda;
>
> * if sequence[index] exists, return that value;
>
> * otherwise return the default value;
>
> * it should support both positive and negative indices.
>
> Example: given an index of 2 and a default of "spam":
>
>     (lambda seq: ... )("abcd") returns "c"
>
>     (lambda seq: ... )("") returns "spam"
>
>
> I might be missing something horribly obvious, but I can't see how to do 
> this using a lambda. I tried using slicing:
>
>     seq[index:index+1]
>
> which will return either an empty slice or a one-item slice, but that 
> didn't help me. I feel I'm missing something either obvious, or something 
> impossible, and I don't know which.
>
> (This isn't a code-golf problem. I care more about being able to do it at 
> all, than about doing it in the minimum number of characters.)

This seems to work:

f = (lambda seq: (list(seq) + 3 * ["spam"])[2])




More information about the Python-list mailing list