Funciones
A medida que nuestro código fuente crece, surge la necesidad de organizarlo. Las funciones nos ayudan en la organización.
# Usa 'def' para crear nuevas funciones
def add(x, y):
print("x es {} y y es {}".format(x, y))
return x + y # Retorna valores con una la declaración return
# Llamando funciones con parámetros
add(5, 6) #=> imprime "x es 5 y y es 6" y retorna 11
# Otra forma de llamar funciones es con argumentos de palabras claves
add(y=6, x=5) # Argumentos de palabra clave pueden ir en cualquier orden.
En el ejemplo anterior creamos una función add
que recibe los argumentos a
y b
. Sin embargo, podemos recibir un número variable de argumentos (a
, b
, c
...)
# Puedes definir funciones que tomen un número variable de argumentos
def varargs(*args):
return args
varargs(1, 2, 3) #=> (1,2,3)
# Puedes definir funciones que toman un número variable de argumentos
# de palabras claves
def keyword_args(**kwargs):
return kwargs
# Llamémosla para ver que sucede
keyword_args(pie="grande", lago="ness") #=> {"pie": "grande", "lago": "ness"}
# Puedes hacer ambas a la vez si quieres
def todos_los_argumentos(*args, **kwargs): # *args son argumentos posicionales en los que el orden importa
print(args)
print(kwargs)
"""
todos_los_argumentos(1, 2, a=3, b=4) imprime:
(1, 2)
{"a": 3, "b": 4}
"""
# ¡Cuando llames funciones, puedes hacer lo opuesto a varargs/kwargs!
# Usa * para expandir tuplas y usa ** para expandir argumentos de palabras claves.
args = (1, 2, 3, 4)
kwargs = {"a": 3, "b": 4}
todos_los_argumentos(*args) # es equivalente a foo(1, 2, 3, 4)
todos_los_argumentos(**kwargs) # es equivalente a foo(a=3, b=4)
todos_los_argumentos(*args, **kwargs) # es equivalente a foo(1, 2, 3, 4, a=3, b=4)
Lambdas
También conocidas como funciones anónimas porque no tienen un nombre.
- Se escribe en una única sentencia (línea).
- No tiene nombre (anónima).
- Su cuerpo conlleva un return implícito.
- Puede recibir cualquier número de parámetros.
(lambda x: x > 0)(3) #=> True
La función anterior es equivalente a:
def is_positivo(x):
return x > 0
De hecho, como las lambdas son funciones, podemos asignarlas a variables y usarlas como cualquier otra función.
is_positivo = lambda x: x > 0
is_positivo(-1) #=> False
Generadores
Es una forma sencilla de crear iteradores. Es una función que usando la palabra clave yield
retorna un valor y conserva su estado, permitiendo que la función continúe donde se quedó.
def contador(max):
i = 0
while i < max:
yield i
i += 1
for i in contador(5):
print(i)
Closures
En Python todo es un Objeto, ¡las funciones también!
# Python tiene funciones de primera clase
def crear_suma(x):
def suma(y):
return x + y
return suma
sumar_10 = crear_suma(10) # Podemos guardar en una variable una función definida por nosotros.
sumar_10(3) #=> 13
# Podemos usar listas por comprensión para mapeos y filtros
[sumar_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
# también hay diccionarios
{k:k**2 for k in range(3)} #=> {0: 0, 1: 1, 2: 4}
# y conjuntos por comprensión
{c for c in "la cadena"} #=> {'d', 'l', 'a', 'n', ' ', 'c', 'e'}
Funciones de orden superior
Se conocen en inglés como higher-order functions y son funciones que reciben otras funciones como argumentos.
En Python, todo es un objeto, incluidas las funciones. Esto significa que, al igual que podemos asignar una función a una variable, también podemos pasar funciones como argumentos a otras funciones.
Usando esta estrategia podríamos explotar el paradigma de la programación funcional con python.
En concreto, python nos provee de algunas funciones de orden superior como lo son map
y filter
.
def make_multiplier_of(n):
def multiplier(x):
return x * n
return multiplier # factoría de funciones
m3 = make_multiplier_of(3)
list(map(m3, [1,2,3])) #=> [3, 6, 9]
list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) #=> [6, 7]
Recursividad
Una función puede llamarse a sí misma. Aquí tienes un ejemplo de cómo se vería una función recursiva que calcula el factorial de un número:
def factorial(x):
if x == 1: # Esto es el caso base
return 1
else:
return x * factorial(x - 1)
factorial(5) #=> 120
En las funciones recursivas, es importante tener un caso base que detenga la recursión. En caso contrario, la función se llamará a sí misma infinitamente y Python lanzará un error.