Funciones de orden superior en Python. Clase 26

Anuncio
Funciones como parámetros,
funciones como resultados
Introducción a la Computación
Patricia Borensztejn
Clase 26
Funciones de orden superior
• Se llama así a la técnica que permite pasar
funciones como parámetros (C y Python lo
permiten) y devolver funciones como resultado
(C y Python lo permiten)
• Vamos a centrarnos en la sintaxis de Python, que
es bastante mas sencilla que la de C, pues, en C,
para usar estas funciones de orden superior,
debemos primero crear punteros a funciones, y si
ya son complicados los punteros a datos,
imaginen ustedes los punteros a funciones….
Ejemplo
• Explicación:
– La función saludar
contiene:
• 3 funciones, un
diccionario.
• Devuelve el valor de
un diccionario que es
una de las 3 funciones
– Luego se puede
invocar la función
como siempre
def saludar(lang):
def saludar_es():
print “Hola”
def saludar_en():
print “Hi”
def saludar_fr():
print “Salut”
lang_func = ,“es”: saludar_es,
“en”: saludar_en,
“fr”: saludar_fr}
return lang_func[lang]
f = saludar(“es”)
f()
Las funciones son variables
• Como vemos, las funciones son
variables , y en python las variables
son objetoslas funciones son
objetos.
• Lo cual no es ninguna novedad ya
que dijimos que TODO en Python
es objeto.
• Una sintaxis alternativa no utiliza la
variable auxiliar f.
• En este caso, el primer par de
paréntesis corresponde al
parámetro de saludar, y el segundo
al parámetro de la función devuelta
por saludar.
f = saludar(“es”)
f()
>>> saludar(“en”)()
Hi
>>> saludar(“fr”)()
Salut
Map, Filter, Reduce
• Son tres funciones donde podemos utilizar
como parámetros las funciones de orden
superior y que permiten sustituir los bucles
típicos de los lenguajes de programación
imperativos.
map(function, sequence[, sequence, ...])
• Explicación:
– La función map aplica una
función a cada elemento
de una secuencia y
devuelve una lista con el
resultado de aplicar la
función a cada elemento.
– Si se pasan como
parámetros n secuencias,
la función tendrá que
aceptar n argumentos.
(??)
def cuadrado(n):
return n ** 2
l = [1, 2, 3]
l2 = map(cuadrado, l)
filter(function, sequence)
• Explicación:
– La funcion filter verifica que
los elementos de una
secuencia cumplan una
determinada condición,
devolviendo una secuencia
con los elementos que
cumplen esa condición.
– Es decir, para cada elemento
de sequence se aplica la
función function; si el
resultado es True se añade a
la lista y en caso contrario se
descarta.
def es_par(n):
return (n % 2.0 == 0)
l = [1, 2, 3]
l2 = filter(es_par, l)
reduce(function, sequence[, initial])
• Explicación:
– La función reduce aplica
una función a pares de
elementos de una
secuencia hasta dejarla en
un solo valor
– El ejemplo suma todos los
elementos de una lista
def sumar(x, y):
return x + y
l = [1, 2, 3]
l2 = reduce(sumar, l)
Funciones lambda
• Existe un operador llamado
lambda que sirve para crear
funciones anónimas, (on
line) que no podrán ser
utilizadas luego pues no
tienen nombre.
• Las funciones lambda se
construyen mediante el
operador lambda, los
parámetros de la función
separados por comas
(atención, SIN paréntesis),
dos puntos (:) y el código de
la función.
def es_par(n):
return (n % 2.0 == 0)
l = [1, 2, 3]
l2 = filter(es_par, l)
l = [1, 2, 3]
l2 = filter(lambda n: n % 2.0 == 0, l)
Comprensión de listas
• La comprensión de listas es una característica tomada
del lenguaje de programación funcional Haskell que
está presente en Python desde la versión 2.0 y consiste
en una construcción que permite crear listas a partir de
otras listas.
• Es una técnica que va a reemplazar a las funciones
map, filter y reduce a partir de Python 3.0
• Cada una de estas construcciones consta de una
expresión que determina cómo modificar el elemento
de la lista original, seguida de una o varias clausulas for
y opcionalmente una o varias clausulas if.
Comprensión de listas
def cuadrado(n):
return n ** 2
def es_par(n):
return (n % 2.0 == 0)
l = [1, 2, 3]
l2 = map(cuadrado, l)
l = [1, 2, 3]
l2 = filter(es_par, l)
l2 = [n ** 2 for n in l]
l2 = [n for n in l if n % 2.0 == 0]
l = [0, 1, 2, 3]
m = *“a”, “b”+
n = []
for s in m:
for v in l:
if v > 0:
n.append(s* v)
l = [0, 1, 2, 3]
m = *“a”, “b”+
n = [s * v for s in m
for v in l
if v > 0]
Decoradores
• Un decorador no es es mas que una función que recibe una
función como parámetro y devuelve otra función como
resultado.
• Por ejemplo podríamos querer añadir la funcionalidad de que se
imprimiera el nombre de la función llamada por motivos de
depuración
def mi_decorador(funcion):
def nueva(*args):
print “Llamada a la funcion”, funcion.__name__
retorno = funcion(*args)
return retorno
return nueva
• Como vemos el código de la función mi_decorador no hace más
que crear una nueva función y devolverla. Esta nueva función
imprime el nombre de la función a la que “decoramos”, ejecuta
el código de dicha función, y devuelve su valor de retorno.
Decoradores
def mi_decorador(funcion):
def nueva(*args):
print “Llamada a la funcion”, funcion.__name__
retorno = funcion(*args)
return retorno
return nueva
>>> imp(“hola”)
hola
>>> mi_decorador(imp)(“hola”)
Llamada a la función imp
hola
Descargar