suma resueltos propias otra lista globales función funciones funcion ejercicios ejemplos dentro python functional-programming currying partial-application

resueltos - lista de funciones de python



En Python, aplicación de función parcial(currying) versus definición de función explícita (2)

En Python, se considera mejor estilo para:

  • definir explícitamente funciones útiles en términos de funciones más generales, posiblemente de uso interno; o,
  • utilizar la aplicación de función parcial para describir explícitamente el currying de la función?

Explicaré mi pregunta por medio de un ejemplo artificial.

Supongamos que uno escribe una función, _sort_by_scoring, que toma dos argumentos: una función de puntuación y una lista de elementos. Devuelve una copia de la lista original ordenada por puntajes según la posición de cada elemento dentro de la lista original. También se proporcionan dos ejemplos de funciones de puntuación.

def _sort_by_score(scoring, items_list): unsorted_scored_list = [(scoring(len(items_list), item_position), item) for item_position, item in enumerate(items_list)] sorted_list = [item for score, item in sorted(unsorted_scored_list)] return sorted_list def _identity_scoring(items_list_size, item_position): return item_position def _reversed_scoring(items_list_size, item_position): return items_list_size - item_position

La función _sort_by_score nunca se llama directamente; en su lugar, es llamado por otras funciones de argumento único que pasan una función de puntuación y su único argumento (una lista de elementos) a _sort_by_scoring y devuelve el resultado.

# Explicit function definition style def identity_ordering(items_list): return _sort_by_score(_identity_scoring, items_list) def reversed_ordering(items_list): return _sort_by_score(_reversed_scoring, items_list)

Obviamente, esta intención se expresa mejor en términos de función de currying.

# Curried function definition style import functools identity_ordering = functools.partial(_sort_by_score, _identity_scoring) reversed_ordering = functools.partial(_sort_by_score, _reversed_scoring)

Uso (en cualquier caso):

>>> foo = [1, 2, 3, 4, 5] >>> identity_ordering(foo) [1, 2, 3, 4, 5] >>> reversed_ordering(foo) [5, 4, 3, 2, 1]

Ventajas aparentes del estilo de definición de función explícita:

  1. las funciones útiles pueden definirse antes que las funciones más generales, sin generar NameErrors;
  2. las funciones de ayuda (p. ej., funciones de puntuación) podrían definirse dentro del cuerpo de definición de función;
  3. posiblemente más fácil de depurar;
  4. el código se ve bien en virtud de "explícito es mejor que implícito".

Ventajas aparentes del estilo de definición de función al curry:

  1. expresa la intención de la programación funcional idiomáticamente;
  2. el código se ve bien en virtud de la concisión.

Para definir funciones "útiles", ¿cuál de los dos estilos es el preferido? ¿Hay otros estilos que sean más idiomáticos / Pythonic / etc.?


Como una ligera tangente, generalmente es deseable dejar que el edificio sorted haga tanto como decorar, clasificar y decorar como sea práctico. Por ejemplo:

def _sort_by_score(scoring, items_list): num_items = len(items_list) def score(entry): return scoring(num_items, entry[0]) return [item for position, item in sorted(enumerate(items_list), key=score)]

(Solo se publica como respuesta porque los bloques de código no funcionan como comentarios. Consulte la respuesta de Sven para obtener una respuesta a la pregunta real).

Editar por otra persona : la función de ordenación de Python recorre la lista y genera la lista de claves primero. La función key() se llama solo una vez para cada elemento de la lista, en el orden de la lista de entrada. Por lo tanto, también puede usar la siguiente implementación:

def _sort_by_score(scoring, items_list): num_items = len(items_list) index = itertools.count() def score(entry): return scoring(num_items, next(index)) return sorted(items_list, key=score)

(Solo se publica como revisión porque los bloques de código no funcionan como comentarios).


Si desea tener las funciones con curry como parte de una interfaz pública, use definiciones explícitas de funciones. Esto tiene las siguientes ventajas adicionales:

  1. Es más fácil asignar una docstring a una definición de función explícita. Para funciones partial() , tendría que asignar al atributo __doc__ , que es algo feo.

  2. Las definiciones de funciones reales son más fáciles de escanear al explorar el origen del módulo.

Utilizaría functools.partial() de manera similar a las expresiones lambda, es decir, para las funciones desechables localmente necesarias.

En su ejemplo particular, probablemente no usaría ninguno de los dos, soltar los guiones bajos principales y llamar

sort_by_score(identity_scoring, foo)

que me parece el más explícito.