2012-07-02 35 views
24

Hay una cuestión más general aquí: In what situation should the built-in operator module be used in python?¿Por qué debería usar operator.itemgetter (x) en lugar de [x]?

La respuesta más común afirma que operator.itemgetter(x) es "más limpio" que, presumiblemente, de lambda a: a[x]. Siento que lo opuesto es verdad.

¿Hay algún otro beneficio, como el rendimiento?

+0

Su justo más claras cuando sus filtros de escritura o lambdas –

+0

si trabaja en equipo con otros desarrolladores que utilizan lambdas, entonces usted debe utilizar un lambdas :) Como – astynax

+0

pedido, supongo la respuesta correcta a su pregunta es "Nunca". Pero, de hecho, quería saber sobre situaciones ** en las que no puede usar '[x]' solo así **. –

Respuesta

17

No debe preocuparse por el rendimiento a menos que su código esté en un bucle interno cerrado, y en realidad es un problema de rendimiento. En su lugar, use el código que mejor exprese su intención. A algunas personas les gustan las lambdas, otras les gusta el objeto de cambio de objetos. A veces es solo una cuestión de gusto.

itemgetter es más potente, por ejemplo, si necesita obtener una serie de elementos a la vez. Por ejemplo:

operator.itemgetter(1,3,5) 

es lo mismo que:

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

"itemgetter es más poderoso"? Eso parece estar al revés; Puedo hacer muchas cosas con una lambda que no puedo hacer con itemgetter. Puede ser más compacto, supongo. – DSM

+0

@DSM: Creo que se refería a los poderosos en términos de rendimiento C en lugar de flexibilidad – jdi

+6

Estoy bastante seguro de que Ned quería decir que es más poderoso que el operador [], que fue lo que preguntó el interrogador. Obviamente no tiene sentido que sea más poderoso que el código arbitrario de Python en una lambda. –

9

rendimiento. Puede hacer una gran diferencia. En las circunstancias adecuadas, puede obtener un montón de cosas hechas en el nivel C utilizando itemgetter.

creo que la afirmación más clara de lo que es realmente depende de lo que se utiliza con más frecuencia y sería muy subjetiva

11

Hay ventajas en algunas situaciones, esto es un buen ejemplo.

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

Este uso de itemgetter es grande, ya que hace que todo sea claro al mismo tiempo ser más rápido que todas las operaciones se mantienen en el lado C.

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

El uso de un lambda no es tan clara, sino que también es más lento y se prefiere no usar lambda menos que sea necesario. P.ej. las listas de comprensión son preferibles a usar map con lambda.

+11

Personalmente encuentro lambdas más claro en estos casos. Lo que es "claro" no es un reclamo objetivo. 'itemgetter' y sus amigos no son más que lambdas (conceptualmente). Sospecho que las personas que * ya están cómodas * con lambdas en general (quizás porque hacen mucha programación funcional) encuentran 'lambda' más clara (ya que ya conocen' lambda' y lo que ya saben 'cosa [índice]', entonces el lambda "simplemente dice lo que significa", mientras que 'itemgetter' requiere memorizar un nombre adicional), mientras que aquellos que no están tan acostumbrados a pensar con lambdas encuentran' itemgetter' más fácil. – Ben

7

Algunos programadores entienden y usan lambdas, pero hay una población de programadores que quizás no tomaron ciencias de la computación y no tienen claro el concepto. Para aquellos programadores itemgetter() puede hacer su intención más clara. (No escribo lambdas y cada vez que veo uno en código me lleva un poco más de tiempo procesar lo que está pasando y entender el código).

Si su codificación para otros profesionales de informática prosiga y utilice lambdas si son más cómodos. Sin embargo, si codifica para un público más amplio, sugiero usar itemgetter().

1

Para agregar a las respuestas existentes, itemgetter es seleccionable, mientras que lambda no lo es. Esto es importante si la función necesita ser guardada, o pasada entre procesos (típicamente como parte de un objeto más grande). En el siguiente ejemplo, reemplazar itemgetter con lambda dará como resultado 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

Como se mencionó rendimiento, he comparado los dos métodos operator.itemgetter y lambda y para obtener una lista pequeña resulta que supera a operator.itemgetter lambda por 10%.Personalmente me gusta el método itemgetter, ya que lo uso principalmente durante la ordenación y se convirtió en una palabra clave para mí.

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 

Ejecutar en Python 3.6

Cuestiones relacionadas