2012-02-28 12 views
27

Hay una sugerencia de semi-famous article written by Guido himself que reduce() debe seguir el camino del dodo y dejar el idioma. Incluso fue degradado de ser una función de nivel superior en Python 3 (instead getting stuffed in the functools module).Python alternative to reduce()

Con muchas otras grapas de programación funcional (mapa, etc.) hay disponibles alternativas claras comunes. Por ejemplo, la mayoría de las veces, un map() se escribe mejor como una lista de comprensión.

Lo que me gustaría saber es si existe una alternativa "más pitónica" similar a la función de reducción. Tengo un poco de experiencia en programación funcional (ML en particular), así que reduce() a menudo me viene a la mente cuando pienso en una solución, pero si hay una mejor manera de hacerlo (a menos de desenrollar una llamada reducida en un bucle for) me gustaría saber

+5

Bueno, siempre puedes hacer un 'desde la importación de functools reduce'. –

+1

Si piensa en términos de "reducir", "doblar", "mapa", etc., no creo que deba cambiar su forma de pensar. Ya estás en buenas pistas. – Irfy

+0

@NiklasB .: Sé que puedes importarlo de los functools (ese hecho fue aludido en mi pregunta). –

Respuesta

23

Como el artículo vinculado de Guido dice, simplemente debe escribir un ciclo for explícito si desea evitar reduce(). Se puede reemplazar la línea

result = reduce(function, iterable, start) 

por

result = start 
for x in iterable: 
    result = function(result, x) 
+6

También tenga en cuenta que esto no es 100% equivalente: 'reduce()' como se define en la biblioteca estándar no requiere un argumento de inicio. Por lo tanto, debe colocar un protector alrededor del bucle for para verificar si iterable está vacío, si no lo está, tomar el 1er artículo como inicio y pasar el resto de los elementos. De repente, esa línea 'reduce()' se ve aún más atractiva independientemente de lo que piense Guido. ;) –

+1

@AdamParkin: Su último comentario no tiene demasiado sentido. Los dos fragmentos de código son 100% equivalentes (para fines prácticos). Usted * podría * invocar el argumento 'reduce()' sin 'inicio', y luego el equivalente se vería diferente, pero no necesitaría los iterables vacíos de casos especiales más de lo que necesitaría al usar' reduce() ' sin 'inicio'. –

+1

'reduce (set.intersection, list_of_some_sets)' se reduciría hasta la intersección de todos los conjuntos definidos en list_of_some_sets (utiliza implícitamente el primer elt de la lista como inicio). Para desenrollar esto en un bucle tendré que extraer el 1 ° elt (bueno, cualquier elemento) usar eso como mi "inicio", y luego ingresar el bucle iterando sobre los elementos n-1 restantes. Sin embargo, sacar ese primer elemento (o lo que sea) de la lista solo sería válido si sabe que la lista no está vacía, de ahí la necesidad de un guardia. Mira la [definición en los documentos] (http://docs.python.org/library/functions.html#reduce) para lo que quiero decir. –

1

Lo que me gustaría saber es si hay una alternativa similar "más Pythonic" a la función de reducir.

Sí y no. Depende del caso de uso.

En el artículo vinculado, Guido sugiere que la mayoría de las reducciones, pero no todas, deben escribirse como bucles. Hay circunstancias limitadas en las que ve reduce como aplicable.

Así que en mi mente, la aplicabilidad de reducir() es más o menos limitado a operadores asociativos, y en todos los demás casos es mejor para escribir el bucle de acumulación de forma explícita.

No hay muchos operadores asociativos. (Esos son operadores X para los cuales (a X b) X c es igual a X (b X c)). Creo que es casi limitado a +, *, &, |, ^, y acceso directo y/o.

+0

Gran punto, y estoy de acuerdo, aunque esto no es realmente una respuesta a la pregunta, sino más bien (bastante buena) visión relacionada con el artículo citado en la pregunta. Tal vez esto sería más adecuado como un comentario sobre la pregunta que una respuesta sugerida? –

+1

@AdamParkin Punto justo. Reescrito como una respuesta. – kkurian

+0

Encontré su respuesta al decidir si debería usar 'reducir' en mi código. En mi caso, estoy reduciendo a un conjunto de valores únicos de una lista muy grande. Entonces, para lo que vale, me gustaría incluir una unión establecida en su conjunto de operadores asociativos. – Rich