Python funcional o no...

Chema Cortes py en ch3m4.org
Jue Mayo 4 13:45:46 CEST 2006


Rolando Espinoza La Fuente escribió:
> Hola, a manera de práctica implemente el algoritmo el algoritmo de
> dijkstra[1]. El asunto es que hago uso de muchas funciones lambda, y la
> pregunta es que opinan del estilo de programación funcional en python?
> 
> [1] http://darkstar.pinguinos.org/~rolando/dijkstra/


Aunque solemos decir que python es multiparadigma por lo flexible que
es, no es el lenguaje más apropiado para programación "funcional".
Las funciones "no son autenticos objetos" en el sentido de que no son
"instancias" de una clase/tipo de datos, por lo que no se pueden definir
operaciones entre funciones.

Aún con todo, se puede hacer bastante cosas: composición,
"currificación", etc. (En el python 2.5 he visto que hay alguna novedad
sobre paso parcial de argumento, pero no me ha dado tiempo de mirarlo
con detenimiento. Parece una currificación).


Concretando en lo que nos atañe, hay que evitar las funciones lambda.
Está previsto su desaparición futura; el creador del lenguaje, Guido, se
ha lamentado muchas veces de haberlas incluído. Las funciones lambdas
tienen problemas con las "clausuras" ("closures"), y se recomienda usar
en su lugar la definición normal de funciones (o sea, usar siempre
funciones con "nombre").

En cuanto al uso de algunas funciones típicas de la programación
funcional (map, apply, filter, reduce, zip, etc.) se recomienda no
usarlas en favor de expresiones más "pythónicas" ("idioms") como la
comprensión de listas y las expresiones generadoras:


func = lambda x: ....  =>  def func(x): return ...

apply(func, L) => func(*L)
map(func,L)    => [ func(i) for i in L ]
filter(func,L) => [ i for i in L if func(i) ]
zip(L1, L2)    => [ (L1[i],L2[i]) for i in range(len(L1)) ]

reduce(func,L) => res=func(L[0],L[1])
                  for i in L[2:]: res=func(res,i)

Tanto 'apply' como 'map' han quedado obsoletas; las demás aún se ven
tanto en su versión normal, como en su versión iterador (módulo
'itertools').


De tu código, algunas recomendaciones:

- se puede prescindir de la marca de continuación de línea '\' cuando
estás enumerando una secuencia (lista/tupla). Seguro que te da mayor
legibilidad.

- no necesitas las expresiones regulares para chequear si una string
contiene o acaba con ':' (alternativas: .endswith() y operador 'in')

- tal vez podrías trabajar con conjuntos ("sets") en lugar de listas (no
quiero meterme en cómo funciona el algoritmo).



Un pequeño trozo refactorizado:


def listsub(A,B):
  return [ k for k in A if k not in B ]

def dlsub(D,L):
  return [ [k,v] for k,v in D.items() if k not in L ]



Si cambias el código, prometo volver a echarle un vistazo.


Saludos,
-- 
Chema Cortés (py en ch3m4.org)
"Proudly made on earth by generic humanoid carbon units"




Más información sobre la lista de distribución Python-es