Funciones
## Objetivos de Aprendizaje
- Definir y llamar funciones
- Entender parámetros y argumentos
- Dominar valores de retorno
- Aprender alcance y cierres
## Definir Funciones
### Función Básica
```python
def saludar():
print("¡Hola!")
saludar() # ¡Hola!
```
### Función con Parámetros
```python
def saludar(nombre):
print(f"¡Hola, {nombre}!")
saludar("Ana") # ¡Hola, Ana!
saludar("Bob") # ¡Hola, Bob!
```
### Función con Valor de Retorno
```python
def sumar(a, b):
return a + b
resultado = sumar(3, 5)
print(resultado) # 8
```
### Función con Múltiples Retornos
```python
def dividir(a, b):
cociente = a // b
residuo = a % b
return cociente, residuo
c, r = dividir(10, 3)
print(f"Cociente: {c}, Residuo: {r}") # Cociente: 3, Residuo: 1
```
## Parámetros por Defecto
```python
def saludar(nombre, saludo="Hola"):
return f"{saludo}, {nombre}!"
print(saludar("Ana")) # Hola, Ana!
print(saludar("Bob", "Hi")) # Hi, Bob!
print(saludar("Carlos", "Hey")) # Hey, Carlos!
```
### Gotcha del Parámetro por Defecto
```python
# ¡No uses argumentos mutables por defecto!
def mala_funcion(items=[]): # MAL
items.append(1)
return items
# Usa None en su lugar
def buena_funcion(items=None):
if items is None:
items = []
items.append(1)
return items
```
## Argumentos de Palabra Clave
```python
def crear_usuario(nombre, edad, ciudad="Desconocida"):
return f"{nombre}, {edad}, {ciudad}"
# Posicional
print(crear_usuario("Ana", 25)) # Ana, 25, Desconocida
# Palabra clave
print(crear_usuario(nombre="Bob", edad=30)) # Bob, 30, Desconocida
print(crear_usuario(edad=35, nombre="Carlos")) # Carlos, 35, Desconocida
# Mixto
print(crear_usuario("Diana", ciudad="Barcelona", edad=28)) # Diana, 28, Barcelona
```
## *args y **kwargs
### *args (Posicional Variable)
```python
def sumar_todo(*args):
total = 0
for num in args:
total += num
return total
print(sumar_todo(1, 2, 3)) # 6
print(sumar_todo(1, 2, 3, 4, 5)) # 15
```
### **kwargs (Palabra Clave Variable)
```python
def imprimir_info(**kwargs):
for clave, valor in kwargs.items():
print(f"{clave}: {valor}")
imprimir_info(nombre="Ana", edad=25, ciudad="Madrid")
# nombre: Ana
# edad: 25
# ciudad: Madrid
```
### Combinados
```python
def func(*args, **kwargs):
print(f"Args: {args}")
print(f"Kwargs: {kwargs}")
func(1, 2, 3, nombre="Ana", edad=25)
# Args: (1, 2, 3)
# Kwargs: {'nombre': 'Ana', 'edad': 25}
```
## Funciones Lambda
### Lambda Básica
```python
cuadrado = lambda x: x ** 2
print(cuadrado(5)) # 25
# Equivalente a:
def cuadrado(x):
return x ** 2
```
### Lambda con Múltiples Argumentos
```python
sumar = lambda a, b: a + b
print(sumar(3, 5)) # 8
```
### Lambda con Sorted
```python
estudiantes = [("Ana", 85), ("Bob", 92), ("Carlos", 78)]
# Ordenar por nombre
por_nombre = sorted(estudiantes, key=lambda x: x[0])
# [("Ana", 85), ("Bob", 92), ("Carlos", 78)]
# Ordenar por nota
por_nota = sorted(estudiantes, key=lambda x: x[1])
# [("Carlos", 78), ("Ana", 85), ("Bob", 92)]
```
### Lambda con map y filter
```python
numeros = [1, 2, 3, 4, 5]
# Map: aplicar función a todos
cuadrados = list(map(lambda x: x ** 2, numeros))
# [1, 4, 9, 16, 25]
# Filter: mantener elementos donde condición es True
pares = list(filter(lambda x: x % 2 == 0, numeros))
# [2, 4]
```
## Alcance
### Regla LEGB
```python
x = "global"
def exterior():
x = "anidado"
def interior():
x = "local"
print(x) # local
interior()
print(x) # anidado
print(x) # global
exterior()
```
### Palabra Clave global
```python
contador = 0
def incrementar():
global contador
contador += 1
incrementar()
incrementar()
print(contador) # 2
```
### Palabra Clave nonlocal
```python
def exterior():
x = "exterior"
def interior():
nonlocal x
x = "interior"
interior()
print(x) # interior
exterior()
```
## Funciones de Primera Clase
Las funciones pueden pasarse como cualquier otro valor:
```python
def aplicar_dos_veces(func, x):
return func(func(x))
def agregar_cinco(x):
return x + 5
print(aplicar_dos_veces(agregar_cinco, 10)) # 20
```
### Funciones como Valores de Retorno
```python
def multiplicador(factor):
def multiplicar(x):
return x * factor
return multiplicar
doblar = multiplicador(2)
triplicar = multiplicador(3)
print(doblar(5)) # 10
print(triplicar(5)) # 15
```
## Decoradores
### Decorador Básico
```python
def decorador(func):
def envoltura():
print("Antes")
func()
print("Después")
return envoltura
@decorador
def decir_hola():
print("¡Hola!")
# Equivalente a: decir_hola = decorador(decir_hola)
```
### Decorador con Argumentos
```python
def repetir(veces):
def decorador(func):
def envoltura(*args, **kwargs):
for _ in range(veces):
func(*args, **kwargs)
return envoltura
return decorador
@repetir(3)
def saludar(nombre):
print(f"¡Hola, {nombre}!")
saludar("Ana")
# ¡Hola, Ana! (3 veces)
```
## Sugerencias de Tipo
### Sugerencias de Tipo Básicas
```python
def sumar(a: int, b: int) -> int:
return a + b
def saludar(nombre: str) -> None:
print(f"Hola, {nombre}")
# Sin efecto en tiempo de ejecución pero ayuda a herramientas
```
### Tipos Complejos
```python
from typing import List, Dict, Optional, Union
def procesar(numeros: List[int]) -> Dict[str, int]:
return {"cantidad": len(numeros), "suma": sum(numeros)}
def encontrar(usuario: Optional[str]) -> Union[str, None]:
return usuario if usuario else None
```
## Docstrings
```python
def sumar(a, b):
"""
Suma dos números.
Args:
a: Primer número
b: Segundo número
Returns:
La suma de a y b
Example:
>>> sumar(2, 3)
5
"""
return a + b
```
## Resumen
- Define funciones con `def`
- Parámetros y valores de retorno
- Parámetros por defecto: `def f(x=1)`
- Argumentos de palabra clave: `f(nombre="Ana")`
- `*args` para positional, `**kwargs` para argumentos de palabra clave
- Lambda: `lambda x: x ** 2`
- Alcance: local, anidado, global, builtin (LEGB)
- Decoradores: `@decorador` envuelve una función
- Sugerencias de tipo para documentación
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →