2010-06-06 17 views
21

Veo lo que parece ser la mayoría de los desarrolladores de Python en StackOverflow que avalan el uso de herramientas funcionales concisas como lambdas, mapas, filtros, etc., mientras que otros dicen que su código es más claro y más fácil de mantener al no usarlos. ¿Cuál es tu preferencia?¿Utiliza Python principalmente por sus características funcionales u orientadas a objetos?

Además, si usted es un programador funcional incondicional o hardcore en OO, ¿qué otras prácticas de programación específicas utiliza que cree que son las mejores para su estilo?

Gracias de antemano por sus opiniones!

+0

Lo uso para secuencias de comandos rápidas y sucias. Entonces ... imperativo/procesal. –

Respuesta

41

Principalmente utilizo Python utilizando estilos orientados a objetos y procedimientos. Python en realidad no es especialmente adecuado para la programación funcional.

Mucha gente piensa que están escribiendo código Python funcional mediante el uso de una gran cantidad de lambda, map, filter y reduce, pero esto es un poco sobre-simplificado. La característica distintiva de la programación funcional es la falta de estados o efectos secundarios. Los elementos importantes de un estilo funcional son funciones puras, algoritmos recursivos y funciones de primera clase.

Aquí están mis pensamientos sobre la programación funcional y Python:

  • funciones puras son grandes. Hago todo lo posible para que mis funciones a nivel de módulos sean puras.

    • Las funciones puras se pueden probar. Como no dependen del estado externo, son mucho más fáciles de probar.
    • Las funciones puras son compatibles con otras optimizaciones, como la memorización y la paralelización trivial.
  • La programación basada en la clase puede ser pura. Si desea un equivalente a funciones puras utilizando las clases de Python (que es a veces, pero no siempre lo que quiere),

    • Haga sus casos inmutable. En particular, esto significa principalmente hacer que sus métodos siempre devuelvan nuevas instancias de su clase en lugar de cambiar la actual.
    • Use la inyección de dependencia en lugar de obtener cosas (como el módulo importado) del alcance global.
    • Esto puede no ser exactamente lo que usted quiere.
  • No intente evitar el estado todos juntos. Esta no es una estrategia razonable en Python. Por ejemplo, use some_list.append(foo) en lugar de new_list = some_list + [foo], el primero de los cuales es más idiomático y eficiente. (De hecho, muchas de las soluciones "funcionales" que uso la gente en Python son algorítmicamente subóptimas en comparación con las soluciones simples o simples que no son funcionales o son tan funcionales, pero no usan las herramientas de aspecto funcional.)

  • Aprenda las mejores lecciones de la programación funcional, por ejemplo estado mutable es peligroso. Pregúntese, ¿De verdad quiero cambiar esta X o quiero una nueva X?

    • Un lugar muy común esto surge es cuando se procesa una lista. Me gustaría utilizar

      foo = [bar(item.baz()) for item in foo] 
      

      en lugar de

      for index, _ in enumerate(foo): 
          foo[index] = bar(foo[index].baz()) 
      

      y cosas como él. Esto evita los errores confusos donde el mismo objeto de la lista se almacena en otro lugar y no se debe cambiar. (Si se cambia , entonces hay una posibilidad decente de que tenga un error de diseño. Mutar una lista a la que ha hecho referencia en varios lugares no es una buena forma de compartir el estado.)

  • No utilice map y amigos a título gratuito. No hay nada más funcional al hacer esto.

    • map/filter son no más funcionales que las listas por comprensión. Las comprensiones de listas fueron tomadas de Haskell, un lenguaje funcional puro. map y especialmente filter puede ser más difícil de entender que una lista de comprensión. Nunca utilizaría map o filter con una lambda, pero podría hacerlo si tuviera una función que ya existía; Yo uso map un poco decente.
    • Lo mismo vale para itertools.imap/ifilter en comparación con las expresiones del generador. (Estas cosas son algo flojas, que es algo grandioso que podemos tomar prestado del mundo funcional.)
    • No use map y filter para efectos secundarios. Veo esto con map mucho, lo que hace que sea difícil de entender el código, las listas innecesarias y decididamente no es funcional (a pesar de que la gente piensa que debe ser debido a map). Simplemente use un ciclo for.
    • reduce es confuso a excepción de casos muy simples. Python tiene bucles y no hay daño al usarlos.
  • No utilice algoritmos recursivos. Esta es una parte de la programación funcional que Python simplemente no admite. CPython (y creo que todas las demás Python) no son compatibles con la optimización de la cola de cola. Use la iteración en su lugar.

  • Solo use lambda cuando esté definiendo funciones sobre la marcha. Las funciones anónimas no son mejores que las funciones nombradas, las últimas son a menudo más robustas, mantenibles y documentadas.

18

Utilizo las características del lenguaje que hace el trabajo con el código más breve y limpio posible. Si eso significa que tengo que mezclar los dos, lo cual hago bastante a menudo, entonces eso es lo que se hace.

6

Python tiene solo características de programación funcional marginales, así que me sorprendería que mucha gente lo usara especialmente para eso. Por ejemplo, no hay una forma estándar de hacer la composición de la función y la biblioteca estándar reduce() ha quedado en desuso en favor de los bucles explícitos.

Además, no creo que map() o filter() estén generalmente respaldados. En sentido opuesto, usualmente las listas de comprensiones parecen preferidas.

+0

También me gusta la comprensión de listas. Me pregunto si veremos que map() y filter() van por el camino de reducir(). – Eric

+3

Tenga en cuenta que la lista de comprensiones proviene del mundo funcional tanto como 'map' y' filter'. –

+1

"Funciones de programación funcional marginal"? Claro, puede que no tenga tablas hash inmutables, pero 'namedtuple' te acerca bastante a poder escribir cosas puramente funcionales fácilmente. – habnabit

1

Selecciono Python cuando estoy asumiendo un problema que se corresponde bien con una solución de OO. Python solo proporciona una capacidad limitada para programar de una manera funcional en comparación con los lenguajes funcionales completos.

Si realmente quiero programación funcional, uso Lisp.

+0

Ok, eso es bueno saberlo. Supongo que nunca he usado un lenguaje completamente funcional. Voy a tener que mirar dentro de eso. – Eric

+3

Vale la pena señalar que Lisp no es un lenguaje completamente funcional como tampoco lo es Python. Sin embargo, admite la programación funcional "mejor" que Python (para una definición de mejor), de la misma manera que Python admite la programación de OO "mejor" que Lisp (de nuevo, mejor puede significar diferente para algunos). Ambos lenguajes son compatibles con OO, funcionales, de procedimiento, yadda yadda. – RHSeeger

5

La mayoría de las respuestas sobre StackOverflow son respuestas cortas y concisas, y los aspectos funcionales de python hacen que escribir ese tipo de respuestas sea fácil.

Las características OO de Python simplemente no son necesarias en 10-20 líneas de respuestas, por lo que no las ve por aquí tanto.

+1

exactamente, cuando empiezo a escribir, normalmente el prototipo es funcional y cuando se vuelve demasiado grande como para manejar empiezo a poner todo ordenadamente en las clases. – thepandaatemyface

8

Soy un OOP y programador funcional, y estos estilos funcionan muy bien juntos, principalmente porque son completamente ortogonales. Hay muchos lenguajes funcionales orientados a objetos y Python es uno de ellos.

Básicamente, descomponer una aplicación en clases es muy útil cuando se diseña un sistema. Cuando realizas la implementación real, FP ayuda a escribir el código correcto.

También me parece muy ofensivo que insinúe que la programación funcional solo significa "utilizar pliegues en todas partes". Esa es probablemente la mayor y peor idea errónea sobre FP. Mucho se ha escrito sobre ese tema, así que simplemente diré que lo mejor de FP es la idea de combinar funciones simples (, correctas y reutilizables) en funciones nuevas y cada vez más complejas. De esta forma, es bastante difícil escribir un código "casi correcto", ya sea que todo haga exactamente lo que usted desea, o se rompe por completo.

FP en Python principalmente gira en torno a escribir generadores y sus familiares (listas de comprensión) y las cosas en el módulo itertools. Las llamadas explícitas de mapa/filtro/reducción simplemente no son necesarias.

Cuestiones relacionadas