2012-07-02 25 views
24

C'è una questione più generale qui: In what situation should the built-in operator module be used in python?Perché dovrei usare operator.itemgetter (x) invece di [x]?

La risposta superiore sostiene che operator.itemgetter(x) è "più ordinato" che, presumibilmente, di lambda a: a[x]. Sento che è vero il contrario.

Ci sono altri vantaggi, come le prestazioni?

+0

Il suo solo più chiare quando i filtri di scrittura o lambda –

+0

se si lavora in team con altri sviluppatori che utilizzano lambda, quindi si dovrebbe utilizzare un lambda :) – astynax

+0

come chiesto, immagino la risposta giusta alla tua domanda è "Mai". Ma in realtà volevi sapere delle situazioni ** in cui non puoi usare '[x]' solo così **. –

risposta

17

Non dovresti preoccuparti delle prestazioni a meno che il tuo codice non sia in uno stretto circuito interno ed è in realtà un problema di prestazioni. Invece, usa il codice che meglio esprime il tuo intento. Ad alcune persone piacciono i lambda, alcuni come gli artigiani. A volte è solo una questione di gusti.

itemgetter è più potente, ad esempio, se è necessario ottenere un numero di elementi contemporaneamente. Per esempio:

operator.itemgetter(1,3,5) 

è lo stesso:

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

"itemgetter è più potente"? Sembra indietro; Posso fare un sacco di cose con una lambda che non posso fare con itemgetter. Può essere più compatto, immagino. – DSM

+0

@DSM: Penso che volesse dire potente in termini di prestazioni C in contrasto con la flessibilità – jdi

+6

Sono abbastanza sicuro che Ned ha significato che è più potente della operatore [], che era quello che l'interrogante ha chiesto. Ovviamente non ha senso che sia più potente del codice Python arbitrario in un lambda. –

9

Performance. Può fare una grande differenza. Nelle giuste circostanze, puoi ottenere un sacco di cose fatte a livello C usando itemgetter.

penso che l'affermazione di ciò che è più chiara in realtà dipende da che si utilizzano più frequentemente e sarebbe molto soggettivo

11

ci sono benefici in alcune situazioni, ecco un buon esempio.

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

Questo uso della itemgetter è grande perché rende tutto chiaro, mentre anche essere più veloce come tutte le operazioni siano mantenute sul lato C.

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

Utilizzando un lambda non è chiaro, ma è anche più lento e si preferisce non utilizzare lambda a meno che non si deve. Per esempio. le list comprehensions sono preferite rispetto all'utilizzo di map con un lambda.

+11

Personalmente trovo lambda più chiare in questi casi. Ciò che è "chiaro" non è un'affermazione obiettiva. 'itemgetter' e gli amici non sono altro che lambdas particolare (concettualmente). Sospetto che le persone che sono * già a proprio agio * con lambda in generale (forse perché fanno molta programmazione funzionale) trovino 'lambda' più chiaro (dato che già conoscono' lambda' e il già noto 'cosa [indice]', quindi il lambda "dice solo cosa significa", mentre "itemgetter" richiede la memorizzazione di un nome aggiuntivo), mentre chi non è abituato a pensare con lambda trova più semplice "itemgetter". – Ben

7

Alcuni programmatori comprendono e utilizzano lambda, ma esiste una popolazione di programmatori che forse non ha preso l'informatica e che non sono chiari sul concetto. Per quei programmatori itemgetter() puoi rendere più chiara la tua intenzione. (Non scrivo lambda e ogni volta che ne vedo uno in codice mi ci vuole un po 'di tempo in più per elaborare quello che sta succedendo e capire il codice).

Se la codifica per altri professionisti dell'informatica va avanti e utilizzare lambda se sono più confortevoli. Tuttavia, se la tua codifica per un pubblico più ampio ti suggerisco di usare itemgetter().

1

Per aggiungere alle risposte esistenti, itemgetter è selezionabile, mentre non lo è lambda. Questo è importante se la funzione deve essere salvata o passata tra processi (in genere come parte di un oggetto più grande). Nell'esempio seguente, la sostituzione di itemgetter con lambda darà come risultato un 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

Come prestazioni è stato menzionato, ho confrontato entrambi i metodi operator.itemgetter e lambda e per un piccolo elenco si scopre che operator.itemgetter sorpassa lambda da 10%.Personalmente, come il metodo itemgetter come io uso soprattutto durante sorta ed è diventato come una parola chiave per me.

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 su Python 3.6

Problemi correlati