Saltar al contenido principal
Intermedio⏱ 1.5 horas
Prerequisitos: Variables y Tipos · Listas · Bucles
Módulo 03: Funciones y MódulosLección 1 de 2
50% completado

Funciones y Organización en Python

🗺️ Mapa de la Lección

⏱ 1.5 horas🟡 Intermedio

🎯 Qué aprenderás

  • Definir y llamar funciones en Python
  • Usar parámetros y argumentos (posicionales, nombrados, por defecto)
  • Entender el scope y return
  • Usar funciones lambda para código compacto
  • Organizar código reutilizable

🌍 Para qué te sirve

  • Evitar repetir código: escribir lógica una vez, usar muchas veces
  • Organizar código: agrupar funcionalidad relacionada
  • APIs y servicios: cada endpoint es una función
  • Procesamiento de datos: transformar datos con funciones reutilizables
  • Validación: crear funciones de validación reutilizables
  • Cálculos: encapsular fórmulas y operaciones complejas

🎯 ¿Por qué aprender funciones?​

Imagina que tienes que calcular el área de un rectángulo 10 veces en tu código. Podrías escribir base * altura 10 veces, pero ¿qué pasa si te equivocas en una? Tienes que corregir 10 lugares.

Las funciones son fundamentales porque:

  • Evitas repetir código: escribes una vez, usas muchas veces
  • Más fácil de corregir: si hay un error, lo arreglas en un solo lugar
  • Código más legible: calcular_total() es más claro que 15 líneas de código
  • Organización: agrupas código relacionado
  • Reutilización: puedes usar funciones en múltiples proyectos

Sin funciones, tu código sería repetitivo, difícil de mantener y poco profesional.

🌍 Casos reales donde se usa​

Las funciones están en absolutamente todos los programas Python:

  • APIs y servicios: Cada endpoint es una función
  • Procesamiento de datos: Transformar datos con funciones reutilizables
  • Validación: Crear funciones de validación reutilizables
  • Cálculos: Encapsular fórmulas y operaciones complejas
  • Organización: Agrupar funcionalidad relacionada
  • Testing: Cada test es una función

Ejemplo real: Cuando haces login en una app, hay una función validar_usuario() que verifica credenciales. Esa misma función se usa en múltiples lugares del código.

💡 Concepto base​

Las funciones te permiten escribir código una vez y reutilizarlo múltiples veces. Una función es un bloque de código con un nombre que puedes "llamar" cuando lo necesites.

Lo genial de Python: La sintaxis de funciones es muy clara y permite parámetros flexibles, valores por defecto, y múltiples formas de llamarlas.

# Definir una función
def calcular_area(base, altura):
"""Calcula el área de un rectángulo"""
return base * altura

# Usar la función
area = calcular_area(5, 3)
print(f"El área es: {area}")
Resultado esperado:
El área es: 15
🌮 Analogía culinaria

Una función es como la receta para preparar chilaquiles al pastor. Una vez que defines la función preparar_chilaquiles(), puedes usarla cada vez que quieras hacer chilaquiles sin tener que recordar todos los pasos. Puedes incluso pasarle diferentes ingredientes como parámetros: preparar_chilaquiles(salsa="verde", nivel_picante="medio"). La función encapsula el proceso completo y lo hace reutilizable. Cada vez que necesitas chilaquiles, simplemente "llamas" a la función en lugar de seguir todos los pasos manualmente.

Para principiantes

Antes de continuar: Asegúrate de entender Variables, Listas y Bucles. Las funciones agrupan código relacionado y lo hacen reutilizable. Es como crear tus propias herramientas personalizadas.

Conceptos Básicos​

Definir una función​

La sintaxis básica es simple:

def nombre_de_la_funcion():
"""Docstring que explica qué hace la función"""
# Código que hace algo
print("¡Hola desde mi función!")

Desglosando esto:

  • def = define (define una función)
  • nombre_de_la_funcion = el nombre que le das (usa snake_case en Python)
  • () = aquí van los parámetros (por ahora vacío)
  • : = Python necesita esto para indicar que viene un bloque de código
  • El código indentado es lo que hace la función

Llamar una función​

Definir una función no la ejecuta. Tienes que llamarla:

# Llamar la función - simplemente escribe su nombre con paréntesis
nombre_de_la_funcion() # Esto ejecuta el código de la función

Piensa en una función como una receta: definirla es escribir la receta, llamarla es cocinar con esa receta.

Tipos de Funciones​

1. Funciones sin parámetros​

Estas funciones siempre hacen lo mismo, no reciben información externa:

def mostrar_mensaje():
"""Función que muestra un mensaje simple"""
print("¡Bienvenidos al curso de Python!")
print("Espero que aprendan mucho.")

# Usar la función
mostrar_mensaje() # Siempre muestra el mismo mensaje

¿Cuándo usar esto? Cuando necesitas ejecutar el mismo código varias veces pero no necesitas variar nada. Por ejemplo: mostrar un menú, inicializar una conexión, etc.

2. Funciones con parámetros​

Estas funciones reciben información que pueden usar:

def saludar_usuario(nombre, rol):
"""Función que saluda a un usuario específico"""
print(f"¡Hola {nombre}!")
print(f"Tu rol en el sistema es: {rol}")

# Usar la función con diferentes valores
saludar_usuario("Carlos", "Administrador")
# Salida: ¡Hola Carlos!
# Tu rol en el sistema es: Administrador

saludar_usuario("Ana", "Editor")
# Salida: ¡Hola Ana!
# Tu rol en el sistema es: Editor

¿Qué está pasando?

  • nombre y rol son parámetros - variables que la función espera recibir
  • Cuando llamas la función, pasas argumentos - los valores reales
  • La función usa esos valores dentro de su código

Ventaja: Una sola función puede trabajar con diferentes datos. Sin parámetros, tendrías que crear una función diferente para cada usuario.

3. Funciones con valores de retorno​

def calcular_area_rectangulo(base, altura):
"""Calcula el área de un rectángulo"""
area = base * altura
return area

# Usar la función
area_total = calcular_area_rectangulo(10, 5)
print(f"El área es: {area_total}")

Parámetros y Argumentos​

Parámetros posicionales​

def registrar_usuario(nombre, email, edad):
"""Registra un nuevo usuario"""
print(f"Registrando a: {nombre}")
print(f"Email: {email}")
print(f"Edad: {edad}")

# Llamar con argumentos posicionales
registrar_usuario("Juan Pérez", "juan@email.com", 30)

Parámetros con nombres (keyword arguments)​

def registrar_usuario(nombre, email, edad):
"""Registra un nuevo usuario"""
print(f"Registrando a: {nombre}")
print(f"Email: {email}")
print(f"Edad: {edad}")

# Llamar con argumentos con nombres
registrar_usuario(edad=30,
nombre="Juan Pérez",
email="juan@email.com")

Parámetros con valores por defecto​

def crear_reporte(titulo, formato="PDF", imprimir=False):
"""Crea un reporte con opciones por defecto"""
estado = "🖨️ Imprimiendo" if imprimir else "💾 Guardando"
print(f"Generando reporte: {titulo}")
print(f"Formato: {formato}")
print(f"Acción: {estado}")

# Usar con valores por defecto
crear_reporte("Ventas Mensuales")
crear_reporte("Inventario", "Excel")
crear_reporte("Nómina", formato="CSV", imprimir=True)

Tipos de Retorno​

Retorno simple​

def cuadrado(numero):
"""Calcula el cuadrado de un número"""
return numero * numero

resultado = cuadrado(5)
print(f"5 al cuadrado es: {resultado}")

Retorno múltiple (tupla)​

def analizar_datos(datos):
"""Calcula estadísticas básicas de una lista"""
if not datos:
return 0, 0, 0, 0

total = sum(datos)
promedio = total / len(datos)
maximo = max(datos)
minimo = min(datos)

return total, promedio, maximo, minimo

# Usar el retorno múltiple
ventas = [150, 200, 120, 300, 250]
total, prom, max_val, min_val = analizar_datos(ventas)

print(f"Total: {total}")
print(f"Promedio: {prom:.2f}")
print(f"Máximo: {max_val}")
print(f"Mínimo: {min_val}")

Retorno de diccionario​

def crear_perfil(nombre, departamento, antiguedad):
"""Crea un perfil de empleado estructurado"""
perfil = {
'nombre': nombre,
'departamento': departamento,
'antiguedad': antiguedad,
'nivel': 'Senior' if antiguedad >= 5 else 'Junior'
}
return perfil

# Usar la función
empleado = crear_perfil("María López", "IT", 6)
print(f"Perfil: {empleado}")

Alcance de Variables (Scope)​

Variables locales​

def calcular_precio_final(precio):
"""Calcula precio con impuesto"""
tasa_impuesto = 0.16 # Variable local
impuesto = precio * tasa_impuesto
total = precio + impuesto
return total

# tasa_impuesto no existe fuera de la función
precio_final = calcular_precio_final(100)
print(f"Precio final: {precio_final}")

Variables globales​

# Variable global
contador_visitas = 0

def registrar_visita():
"""Incrementa el contador de visitas"""
global contador_visitas
contador_visitas += 1
print(f"Visita registrada. Total: {contador_visitas}")

# Usar la función
registrar_visita()
registrar_visita()

Documentación de Funciones​

Docstrings​

def calcular_descuento(precio, porcentaje):
"""
Calcula el descuento aplicable a un precio.

Args:
precio (float): El precio original del producto.
porcentaje (float): El porcentaje de descuento (0-100).

Returns:
float: El monto del descuento calculado.

Raises:
ValueError: Si el precio o porcentaje son negativos.
"""
if precio < 0 or porcentaje < 0:
raise ValueError("Los valores no pueden ser negativos")

return precio * (porcentaje / 100)

# Usar la función documentada
try:
desc = calcular_descuento(1000, 20)
print(f"Descuento: ${desc}")
except ValueError as e:
print(f"Error: {e}")

Buenas Prácticas​

1. Nombres descriptivos​

# ❌ Malo
def f(x):
return x * 12

# ✅ Bueno
def calcular_salario_anual(salario_mensual):
"""Calcula el salario anual basado en el mensual"""
return salario_mensual * 12

2. Funciones pequeñas y específicas​

# ❌ Malo - función que hace demasiadas cosas
def procesar_pedido(pedido):
# Validar, calcular impuestos, enviar email, actualizar stock...
pass

# ✅ Bueno - dividir en funciones específicas
def validar_pedido(pedido):
pass

def calcular_totales(pedido):
pass

def actualizar_inventario(pedido):
pass

3. Manejo de errores​

def division_segura(a, b):
try:
return a / b
except ZeroDivisionError:
print("Error: Divisor no puede ser cero")
return None

Ejercicios Prácticos​

Ejercicio 1: Calculadora​

def calculadora(operacion, a, b):
"""
Calculadora básica que soporta suma, resta, multiplicación y división.
"""
if operacion == 'suma':
return a + b
elif operacion == 'resta':
return a - b
elif operacion == 'multiplicacion':
return a * b
elif operacion == 'division':
if b != 0:
return a / b
else:
print("Error: División por cero")
return None
else:
print("Operación no reconocida")
return None

# Pruebas
print(f"Suma: {calculadora('suma', 10, 5)}")
print(f"División: {calculadora('division', 10, 2)}")

Ejercicio 2: Sistema de Evaluación​

def evaluar_rendimiento(ventas, meta):
"""
Evalúa el rendimiento de ventas contra una meta.
"""
porcentaje = (ventas / meta) * 100

if porcentaje >= 120:
calificacion = "Excelente"
bono = True
elif porcentaje >= 100:
calificacion = "Bueno"
bono = True
elif porcentaje >= 80:
calificacion = "Regular"
bono = False
else:
calificacion = "Insuficiente"
bono = False

return {
"ventas": ventas,
"meta": meta,
"porcentaje": round(porcentaje, 2),
"calificacion": calificacion,
"aplica_bono": bono
}

# Prueba
resultado = evaluar_rendimiento(15000, 12000)
print(f"Evaluación: {resultado}")

Ejercicio 3: Gestor de Tareas Simple​

class GestorTareas:
def __init__(self):
self.tareas = []

def agregar(self, descripcion, prioridad="normal"):
tarea = {
"id": len(self.tareas) + 1,
"descripcion": descripcion,
"prioridad": prioridad,
"completada": False
}
self.tareas.append(tarea)
print(f"Tarea agregada: {descripcion}")

def listar(self):
print("\n--- Lista de Tareas ---")
for t in self.tareas:
estado = "[x]" if t["completada"] else "[ ]"
print(f"{t['id']}. {estado} {t['descripcion']} ({t['prioridad']})")

def completar(self, id_tarea):
for t in self.tareas:
if t["id"] == id_tarea:
t["completada"] = True
print(f"Tarea {id_tarea} completada.")
return
print("Tarea no encontrada.")

# Uso
gestor = GestorTareas()
gestor.agregar("Revisar correos", "alta")
gestor.agregar("Actualizar documentación")
gestor.listar()
gestor.completar(1)
gestor.listar()

Errores Comunes​

1. Olvidar el return​

Si una función no tiene return, devuelve None por defecto. Asegúrate de retornar los valores que necesitas.

2. Modificar variables globales sin global​

Si intentas asignar valor a una variable global dentro de una función sin declararla como global, Python creará una nueva variable local en su lugar.

3. Argumentos mutables por defecto​

Evita usar listas o diccionarios como valores por defecto en argumentos, ya que mantienen su estado entre llamadas.

# ❌ Malo
def agregar_item(item, lista=[]):
lista.append(item)
return lista

# ✅ Bueno
def agregar_item(item, lista=None):
if lista is None:
lista = []
lista.append(item)
return lista

Recursos Adicionales​

Documentación Oficial​

Bibliografía Recomendada​

  • Fluent Python (Luciano Ramalho) - Capítulo 5: First-Class Functions
  • Effective Python (Brett Slatkin) - Items sobre funciones y argumentos
  • Python Tricks (Dan Bader) - Capítulo sobre funciones y decoradores
  • Python Cookbook, 3rd Ed (Beazley & Jones) - Recetas sobre funciones
  • Clean Code (Robert C. Martin) - Capítulo 3: Functions

Conceptos Relacionados​


Siguiente paso​

Ahora que sabes crear funciones, aprende a organizarlas en módulos y paquetes. Continúa con: Módulos y Paquetes