Почему я должен использовать operator.itemgetter(x) вместо [x]?

Здесь есть более общий вопрос: В какой ситуации должен использоваться встроенный модуль operator в python?

Верхний ответ утверждает, что operator.itemgetter(x) является "опрятным", чем, предположительно, чем lambda a: a[x]. Я считаю, что обратное верно.

Есть ли другие преимущества, такие как производительность?

Ответ 1

Вы не должны беспокоиться о производительности, если ваш код не находится в жестком внутреннем цикле и на самом деле является проблемой производительности. Вместо этого используйте код, который наилучшим образом выражает ваши намерения. Некоторым людям нравятся лямбды, некоторые вроде itemgetter. Иногда это просто вопрос вкуса.

itemgetter более мощный, например, если вам нужно получить сразу несколько элементов. Например:

operator.itemgetter(1,3,5)

совпадает с:

lambda s: (s[1], s[3], s[5])

Ответ 2

В некоторых ситуациях есть преимущества, вот хороший пример.

>>> data = [('a',3),('b',2),('c',1)]
>>> from operator import itemgetter
>>> sorted(data, key=itemgetter(1))
[('c', 1), ('b', 2), ('a', 3)]

Это использование itemgetter отлично, потому что оно делает все понятным, а также быстрее, поскольку все операции хранятся на стороне C.

>>> sorted(data, key=lambda x:x[1])
[('c', 1), ('b', 2), ('a', 3)]

Использование lambda не так ясно, оно также медленнее, и не рекомендуется использовать lambda, если это необходимо. Например. список предпочтительнее использования map с lambda.

Ответ 3

Производительность. Это может иметь большое значение. В правильных обстоятельствах вы можете получить кучу вещей, сделанных на уровне C, используя itemgetter.

Я думаю, что утверждение о том, что яснее, действительно зависит от того, что вы используете чаще всего и было бы очень субъективным

Ответ 4

Некоторые программисты понимают и используют лямбда, но есть популяция программистов, которые, возможно, не занимались информатикой и не поняли эту концепцию. Для тех программистов itemgetter() может сделать ваше намерение более ясным. (Я не пишу лямбды, и в любое время, когда я вижу один в коде, мне нужно немного времени, чтобы обработать то, что происходит и понять код).

Если ваше кодирование для других специалистов в области информатики идет вперед и использует лямбда, если они более удобны. Однако, если ваше кодирование для более широкой аудитории я предлагаю использовать itemgetter().

Ответ 5

Как было упомянуто о производительности, я сравнил оба метода operator.itemgetter и lambda, и для небольшого списка оказалось, что operator.itemgetter превосходит лямбду по 10%. Мне лично нравится метод itemgetter, поскольку я в основном использую его во время сортировки, и он стал для меня ключевым словом.

import operator
import timeit

x = [[12, 'tall', 'blue', 1],
[2, 'short', 'red', 9],
[4, 'tall', 'blue', 13]]


def sortOperator():
    x.sort(key=operator.itemgetter(1, 2))

def sortLambda():
    x.sort(key=lambda x:(x[1], x[2]))


if __name__ == "__main__":
    print(timeit.timeit(stmt="sortOperator()", setup="from __main__ import sortOperator", number=10**7))
    print(timeit.timeit(stmt="sortLambda()", setup="from __main__ import sortLambda", number=10**7))    

>>Tuple: 9.79s, Single: 8.835s
>>Tuple: 11.12s, Single: 9.26s

Запуск на Python 3.6

Ответ 6

Оставляя в стороне производительность и стиль кода, itemgetter можно выбирать, а lambda - нет. Это важно, если функцию необходимо сохранить или передать между процессами (обычно как часть более крупного объекта). В следующем примере замена itemgetter на lambda приведет к PicklingError.

from operator import itemgetter

def sort_by_key(sequence, key):
    return sorted(sequence, key=key)

if __name__ == "__main__":
    from multiprocessing import Pool

    items = [([(1,2),(4,1)], itemgetter(1)),
             ([(5,3),(2,7)], itemgetter(0))]

    with Pool(5) as p:
        result = p.starmap(sort_by_key, items)
    print(result)

Ответ 7

При использовании этого параметра key в sorted() или min(), учитывая выбор между, скажем, operator.itemgetter(1) и lambda x: x[1], первый тип обычно значительно быстрее в обоих случаях:


Использование sorted()

bm

Сравниваемые функции определяются следующим образом:

import operator


def sort_key_itemgetter(items, key=1):
    return sorted(items, key=operator.itemgetter(key))


def sort_key_lambda(items, key=1):
    return sorted(items, key=lambda x: x[key])

Результат: sort_key_itemgetter() быстрее на ~ 10% до ~ 15%.

(Полный анализ здесь)


Использование min()

enter image description here

Сравниваемые функции определяются следующим образом:

import operator


def min_key_itemgetter(items, key=1):
    return min(items, key=operator.itemgetter(key))


def min_key_lambda(items, key=1):
    return min(items, key=lambda x: x[key])

Результат: min_key_itemgetter() быстрее на ~ 20% до ~ 60%.

(Полный анализ здесь)