Skip to content Skip to sidebar Skip to footer

Python: Why Return-type Of Itemgetter Is Not Consistent

Python itemgetter doesn't return tuples of length 0 or 1. For example: from operator import itemgetter def get_something(keys): d = { 'a': 1, 'b': 2,

Solution 1:

Is there some other built-in option if I always want to return a tuple/list given the keys?

just use a comprehension:

[d[k] for k in keys]

In context:

from operator import itemgetter

def get_something(keys):
    d = {
        "a": 1,
        "b": 2,
        "c": 3
    }
    return [d[k] for k in keys]

print(get_something(["a", "b"]))
#[1, 2]
print(get_something(["a"]))
#[1]
print(get_something([]))
#[]

Solution 2:

Part of your confusion comes from the fact that your get_something() func takes a single argument (expected to be an iterable) and unpacks it when passing it to itemgetter(). This results in the return value of get_something() not being "symetric" with it's arguments.

If you defined get_something() to use varargs instead (as itemgetter() does) :

def get_something(*keys):
    d = {
        "a": 1,
        "b": 2,
        "c": 3
    }
    return itemgetter(*keys)(d)

the return values would be more consistant with the arguments, ie:

# ask for 3 keys, get 3 values:
>>> get_something("a", "b", "c")
(1, 2, 3)

# ask for 2 keys, get 2 values:
>>> get_something("a", "b")
(1, 2)

# ask for one key, get 1 value
>>> get_something("a")
1

# all of this with tuple unpacking in mind:

a, b = get_something("a", "b")
a = get_something("a") 

Now the point is that few people would bother using itemgetter() to implement your get_something function - itemgetter has mainly been designed to be used as a callback for sorted() and like functions / methods (where it's current behaviour makes sense), and get_something would more canonically be implemented with a list expression ie:

def get_something(keys):
    d = {
        "a": 1,
        "b": 2,
        "c": 3
    }
    return [d[k] for k in keys]

which would take an iterable and return a (possibly empty) list.


Solution 3:

This behavior is documented in the docs (emphasis is mine):

Return a callable object that fetches item from its operand using the operand’s __getitem__() method. If multiple items are specified, returns a tuple of lookup values

itemgetter does not decide the return type, it is the operand's __getitem__() method.

Wouldn't it be easier/better

"better" is subjective. You can always wrap itemgetter:

def get_something(keys):
    def my_itemgetter():
        r = itemgetter(*keys)(d)
        return (r,) if type(r) is not tuple else r

    d = {
        "a": 1,
        "b": 2,
        "c": 3
    }

    return my_itemgetter()

Post a Comment for "Python: Why Return-type Of Itemgetter Is Not Consistent"