Saltar a contenido

Funciones de Orden Superior

Son funciones capaces de ejecutar a otras funciones especificadas por el usuario. Estas funciones son indicadas por su nombre como argumento de la funcion de orden superior.

funcion de orden superior
def funcion_superior (valor_1, valor_2, funcion_usuario):
    # codigo
    # ...
    funcion_usuario(parametros)
    # ...
ejemplo
# Funcion orden superior
def incrementar_4 (x, f):
    # 'f' es una funcion de entrada
    return f(x) + 4

# Funcion externa
def triplicar(x):
    return x*3

# Uso
x = 7
y = incrementar_4(x, triplicar)
print(y)    # Da (x)*3+4 = 25

Closures

Las 'closures' son funciones de orden superior que dan como retorno una función definida internamente.

Closures - Sintaxis
def nombre_closure():
    def funcion_interna(argumentos):
        # rutina
        return retorno

    return funcion_interna
Ejemplo closure
#definicion 
def sumar_diez():
    def add(valor):
        return valor + 10
    return add  #funcion interna como retorno

#uso
closure_sumar = sumar_diez()
print(closure_sumar(7))     # da 10 + 7 = 17

Una utilidad posible de las closures en englobar varias funciones internas alternativas y poder elegir una u otra dependiendo de un argumento.

Otra utilidad posible es la creación de decoradores, los cuales agregan características a las funciones. Más sobre los decoradores de Python.

Map

La función map() es una funcion de orden superior que facilita el procesamiento de datos iterables (particularmente: listas) por una función especificada, "mapeando" cada elemento de los datos de entrada con los argumentos de la funcion y evitando así el uso de bucles y la asignacion elemento a elemento.

Sintaxis:

objeto_resultado = map(funcion, data_entrada_1, data_entrada_2, ...)

El retorno de la funcion map() es un objeto de clase map (una instancia). Con la función list() se convierte dicho objeto en una lista de valores, recuperando así los resultados de la función interna.

map() - procesamiento de listas
objeto_resultado = map(funcion, lista_entrada)
resultado = list(objeto_resultado)

Ejemplo: elevar al cuadado todos los elementos de un vector

map() - ejemplo uso
def potencia_2 (x):
    return x**2

vector = [2, 5, 14, 3]
objeto = map(potencia_2, vector)
cuadrado = list(objeto)

La funcion map() admite multiples listas de entrada

map() - múltiples iterables
def multiplicar(x,y):
    return x*y

vector = [2, 5, 14, 3]
objeto = map(multiplicar, vector, vector)
cuadrado = list(objeto)

map() acepta funciones lambda como argumento. Ejemplo:

map() - uso lambdas
vector = [2, 5, 14, 3]

cuadrado = list(map(lambda numero: numero **2 , vector) )

Filter

filter() es una función que filtra de la lista de entrada los valores que cumplen con una condición lógica definida por una función especificada.

Sintaxis:

filter() - sintaxis
objeto_filtrados = filter(funcion_logica, data_entrada)
Nuevamente la salida es un objeto de la clase filter y para leer la lista de elementos filtrados hay que recurrir a la funcion list().

Ejemplo: filtrar valores numericos mayores a diez de un vector

ejemplo: valores mayores a 10
def mayor_a_10(x):
    return True if x > 10 else False  

vector = [2, 5, -1, 48,-9,-25, 14, 3]
objeto= filter(mayor_a_10, vector)
filtrados = list(objeto)

filter() también acepta funciones lambda como argumento.

Reduce

reduce() opera con todos los elementos de una lista de entrada, aplicándoles una función especificada de manera acumulativa. Esto permite trabajar con un número no predeterminado de argumentos agrupados dentro de una lista de entrada. Para ser utilizada debe ser importada previamente desde el módulo functools:

Importación de reduce()
from functools import reduce
Ejemplo: una productoria (producto sucesivo) de números englobados en una lista

ejemplo: reduce() para hacer productoria
def producto(x, y): 
    return x*y

vector = [2, 5, -1, -3]
productoria = reduce(producto, vector)
# 'productoria' es 2*5*(-1)*(-3) = 30
Como el retorno de la función reduce() es un valor no hace falta hacer conversiones de tipo adicionales.

Partial

La función partial() permite asignar valores prefijados a una función como argumentos. Devuelve como retorno un objeto de clase 'partial' el cual incluye toda la información agregada y que puede utilizarse como si fuera una función lambda. De esta forma con partial() se puede crear una o varias funciones simplificadas.

La función partial() debe importarse desde el módulo functools:

Importación de partial()
from functools import partial

El formato general de esta función es:

Sintaxis de partial()
objeto_partial = partial( nombre_funcion, arg1 = valor_1, arg2 = valor_2, ...)
En caso de no indicarse los nombres de los argumentos éstos se asignarán en orden de definición.

Los objetos partial se usan igual que cualquier función:

Uso de partial()
valor = objeto_partial(argunentos)

Ejemplo Nª1: cuadrado y cubo con partial()

Ejemplo Nº1: crear varias funciones que calculan distintas potencias de un número de entrada.

# función general, dos parámetros 
def potencia(x, exponente):
    return x**exponente


# se crean objetos 'partial' para casos particulares
cuadrado = partial( potencia, exponente = 2 )
cubo     = partial( potencia, exponente = 3 ) 
Estas funciones se usan fácilmente invocándolas por su nombre:

x = 3   # valor de entrada

print( cuadrado(x))     # 3² = 9
print( cubo    (x))     # 3³ = 27

print(type(cubo))  # devuelve " <class 'functools.partial'> "

Ejemplo Nª2: potencias con partial()

En este ejemplo se crea una lista de funciones que calculan distintas potencias de un número de entrada.

definicion de partials
# función general, dos parámetros 
def potencia(x, exponente):
    return x**exponente

# lista de funciones lambdas
potencias = []
for i in range(10):
    # se fija el exponente
    p = partial( potencia, exponente = i )
    potencias.append(p)
De este modo el índice de la función lambda elegida representa el exponente elegido:

uso de partials
x = 3   # valor de entrada

print( potencias[0](x) )        # 3⁰ = 1
print( potencias[1](x) )        # 3¹ = 3
print( potencias[2](x) )        # 3² = 9
print( potencias[3](x) )        # 3³ = 27
print( potencias[4](x) )        # 3⁴ = 81
# ...