2012-07-02 11 views
24

Jest bardziej ogólne pytanie tutaj: In what situation should the built-in operator module be used in python?Dlaczego powinienem używać operatora.itemgetter (x) zamiast [x]?

Górny odpowiedź wnosi operator.itemgetter(x) jest „neater” niż przypuszczalnie niż lambda a: a[x]. Czuję, że przeciwieństwo jest prawdą.

Czy są jakieś inne korzyści, takie jak wydajność?

+0

Jej tylko jaśniejsze, gdy filtry piśmie lub lambdas –

+0

Jeśli pracujesz w zespole z innymi programistami, którzy wykorzystują lambdy, wtedy należy użyć lambdy :) – astynax

+0

Jak zapytałem, myślę właściwą odpowiedzią na twoje pytanie jest "Nigdy". Ale w rzeczywistości chciałeś wiedzieć o sytuacjach **, w których nie możesz użyć '[x]' właśnie tak **. –

Odpowiedz

17

Nie powinieneś przejmować się wydajnością, chyba że Twój kod jest w ciasnej pętli wewnętrznej i jest faktycznie problemem z wydajnością. Zamiast tego użyj kodu, który najlepiej wyraża twoje zamiary. Niektórzy ludzie lubią lambdy, inni jak itemgetter. Czasami to tylko kwestia gustu.

itemgetter jest bardziej wydajny, na przykład, jeśli potrzebujesz uzyskać wiele elementów naraz. Na przykład:

operator.itemgetter(1,3,5) 

jest taka sama, jak:

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

"itemgetter jest mocniejszy"? Wydaje się, że wstecz; Mogę robić wiele rzeczy z lambdą, których nie mogę zrobić z itemgetter. Może to być bardziej kompaktowy. – DSM

+0

@DSM: Myślę, że miał na myśli mocną pod względem wydajności C w przeciwieństwie do elastyczności – jdi

+6

Jestem prawie pewien, że Ned miał na myśli silniejszą niż operator [], o co pytał. Oczywiście nie ma sensu, że jest silniejszy niż dowolny kod Pythona w lambda. –

9

Performance. To może zrobić dużą różnicę. W odpowiednich okolicznościach można uzyskać kilka rzeczy wykonanych na poziomie C za pomocą itemgetter.

Myślę, że twierdzenie o tym, co jest jaśniejsze naprawdę zależy od tego, które używasz najczęściej i byłoby bardzo subiektywne

11

Są to korzyści w pewnych sytuacjach, jest tu dobrym przykładem.

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

Takie wykorzystanie itemgetter jest wielki, ponieważ to sprawia, że ​​wszystko jasne, a jednocześnie jest szybsze, ponieważ wszystkie operacje są przechowywane po stronie C.

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

Korzystanie lambda nie jest tak oczywiste, jest również wolniejszy i korzystne jest, aby nie używać lambda chyba trzeba. Na przykład. sprawdzanie listy są preferowane w stosunku do używania map z lambda.

+11

Osobiście uważam, że lambda jest bardziej przejrzysta w tych przypadkach. To, co jest "jasne", nie jest roszczeniem obiektywnym. 'itemgetter' i przyjaciele są niczym więcej niż konkretną nazwą lambdas (koncepcyjnie). Podejrzewam, że ludzie, którzy * już czują się komfortowo * z lambdami w ogóle (być może dlatego, że wykonują wiele funkcjonalnych programów) znajdują '' 'jaśniejszy '(ponieważ znają już' lambda' i już wiem 'rzecz [indeks]', więc lambda "tylko mówi, co to znaczy", podczas gdy 'itemgetter' wymaga zapamiętywania dodatkowej nazwy), podczas gdy ci, którzy nie są tak przyzwyczajeni do myślenia z lambdami, łatwiej odnajdują' itemgetter'. – Ben

7

Niektórzy programiści rozumieją i używają lambdas, ale jest populacja programistów, którzy być może nie brali nauki informatycznej i nie rozumieją tej koncepcji. Dla tych programistów, itemgetter() może uczynić twój zamiar bardziej przejrzystym. (Nie piszę lambdas i kiedy widzę kod, zajmuje mi to trochę więcej czasu, aby przetworzyć to, co się dzieje i zrozumieć kod).

Jeśli twoje kodowanie dla innych informatyków idzie naprzód i używają lambdas, jeśli są bardziej wygodne. Jeśli jednak twoje kodowanie dla szerszego grona odbiorców sugeruję użycie itemgetter().

1

Aby dodać do istniejących odpowiedzi, można wybrać opcję itemgetter, natomiast lambda nie jest. Jest to ważne, jeśli funkcja musi zostać zapisana lub przekazana między procesami (zazwyczaj jako część większego obiektu). W poniższym przykładzie zastąpienie itemgetter przez lambda spowoduje, że pojawi się 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) 
1

Ponieważ wydajność wspomniano, mam porównaniu obu metod operator.itemgetter i lambda i za niewielką listy okazuje się, że operator.itemgetter przewyższa lambda przez 10%.Osobiście lubię metodę itemgetter, ponieważ używam jej głównie podczas sortowania i stała się dla mnie jak słowo kluczowe.

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 

Run na Pythonie 3.6

Powiązane problemy