Saltar al contenido principal
Intermedio1.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