def square1(n):
"""
Calcula el cuadrado de n y lo regresa. Versión 1.0
"""
result = n**2
return resultApéndice P — Funciones lambda.
Objetivo. Describir el funcionamiento de la expresión lambda.
P.1 Programación funcional.
Es un paradigma de programación basado en el uso de funciones, entendiendo el concepto de función según su definición matemática.
Tiene sus raíces en el cálculo lambda (un sistema formal desarrollado en los años 1930 para investigar la definición de función, la aplicación de las funciones y la recursión).
Muchos lenguajes de programación funcionales pueden ser vistos como elaboraciones del cálculo lambda.
Las funciones que se usan en este paradigma son funciones puras, es decir, que no tienen efectos secundarios, que no manejan datos mutables o de estado.
Lo anterior está en contraposición con la programación imperativa.
Uno de sus principales representantes es el lenguaje Haskell, que compite en belleza, elegancia y expresividad con Python.
Los programas escritos en un estilo funcional son más fáciles de probar y depurar.
Por su característica modular facilita el cómputo concurrente y paralelo.
El estilo funcional se lleva muy bien con los datos, permitiendo crear algoritmos y programas más expresivos para trabajar en Big Data.
P.2 Lambda expressions
Una expresión Lambda (Lambda expressions) nos permite crear una función “anónima” (sin nombre). De esta manera es posible crear funciones ad-hoc sin la necesidad de definir una función propiamente con el comando
def.Una expresión Lambda o función anónima, es una expresión simple, no un bloque de declaraciones.
Solo hay que escribir el resultado de una expresión en vez de regresar un valor explícitamente.
Dado que se limita a una expresión, una función anónima es menos general que una función normal creada con
def.
Por ejemplo, para calcular el cuadrado de un número podemos escribir la siguiente función:
print(square1(5))25
Se puede reducir el código anterior como sigue:
def square2(n):
"""
Calcula el cuadrado de n y lo regresa. Versión 2.0
"""
return n**2print(square2(5))25
Se puede reducir aún más, pero puede llevarnos a un mal estilo de programación. Por ejemplo:
def square3(n): return n**2print(square3(5))25
P.2.1 Definición.
La sintáxis de una expresión lambda en Python (función lambda o función anónima) es muy simple:
lambda argument_list: expression
- La lista de argumentos,
argument_list, consiste de objetos separados por coma. - La expresión,
expression, es cualquiera que sea válida en Python.
Se puede asignar la función a una variable para darle un nombre.
# Se crea una función anónima
lambda n: n**2<function __main__.<lambda>(n)>
Para poder usar la función anterior debe estar en un contexto donde pueda ser ejecutada o podemos darle un nombre como sigue:
# La función anónima se llama ahora cuadrado()
cuadrado = lambda num: num**2# Usamos la función cuadrado()
print(cuadrado(7))49
.
# Construimos la función cubo() usando la función cuadrado()
cubo = lambda n: cuadrado(n) * ncubo(5)125
.
Este ejemplo nos permite mostrar que es posible combinar la definición de funciones normales de Python con las funciones lambda.
def potencia(n):
return lambda a: a ** n # regresa una función lambda# Creamos dos funciones.
cuadrado = potencia(2) # función para elevar al cuadrado
cubo = potencia(3) # función para elevar al cuboprint(cuadrado(5))
print(cubo(2))25
8
.
En este ejemplo vemos como una función lambda puede recibir más de un argumento.
mult = lambda a, b: a * bprint(mult(5,3))15
.
En este ejemplo usamos el operador ternario para probar una condición.
esPar = lambda n: False if n % 2 else Trueprint(esPar(2))
print(esPar(3))True
False
.
firstLast= lambda s: (s[0], s[-1])# Cadena
firstLast('Pythonico')('P', 'o')
# Lista
firstLast([1,2,3,4,5,6,7,8,9])(1, 9)
# Tupla
firstLast( (1.2, 3.4, 5.6, 8.4) )(1.2, 8.4)
.
c = 'Pythonico'
reversa = lambda l: l[::-1]
print(c)
print(reversa(c))Pythonico
ocinohtyP
P.3 Funciones puras e impuras
La programación funcional busca usar funciones puras, es decir, que no tienen efectos secundarios, no manejan datos mutables o de estado.
Estas funciones puras devuelven un valor que depende solo de sus argumentos.
Por ejemplo, podemos construir funciones que hagan un cálculo aritmético el cuál solo depende de sus entradas y no modifica otra cosa:
# La siguiente es una función pura
def operacion1(x, y):
return (x + 2 * y) / (2 * x + y)
operacion1(1,2)1.25
# La siguiente es una función lambda pura
operacion2 = lambda x, y: (x + 2 * y) / (2 * x + y)
operacion2(1,2)1.25
El que sigue es un ejemplo de una función impura que tiene efectos colaterales en la lista:
lista = [] # lista vacía
# Esta es una función impura
def operacion3(arg):
potencia = 2
lista.append(arg) # Se modifica la lista
return arg ** potencia
operacion3(5)
print(lista)[5]
Lo anterior también puede suceder usando funciones lambda:
# Función lambda impura:
operacion4 = lambda l, arg : (l.append(arg), arg**2)print(operacion4(lista,5))
lista(None, 25)
[5, 5]
Una práctica recomendable del estilo funcional es evitar los efectos secundarios, es decir, que nuestras funciones, en la medida de lo posible, NO modifiquen los valores de sus argumentos.