Crear funciones con def
🧭 Navegación:
- Anterior: Funciones – Bloques de Construcción para Reutilización
- Siguiente: Parámetros y argumentos
¡Bienvenido al taller de creación de herramientas de nuestro almacén! Las funciones son como máquinas especializadas que podemos diseñar y construir para automatizar tareas específicas. Una vez que aprendas a crearlas, tu eficiencia como “gerente del almacén” se multiplicará exponencialmente.
🏭 ¿Qué es una función?
Imagina que en tu almacén tienes que calcular el precio final de productos con descuentos e impuestos todo el tiempo. En lugar de hacer estos cálculos manualmente cada vez, puedes construir una máquina calculadora de precios que:
- Reciba el precio original como entrada
- Procese los cálculos internamente
- Entregue el precio final como resultado
Esa máquina es una función en programación.
# Antes: Cálculos repetitivos y propensos a errores
precio_laptop = 1500
precio_laptop_con_descuento = precio_laptop * 0.90 # 10% descuento
precio_laptop_final = precio_laptop_con_descuento * 1.16 # 16% impuesto
precio_mouse = 35
precio_mouse_con_descuento = precio_mouse * 0.90
precio_mouse_final = precio_mouse_con_descuento * 1.16
precio_teclado = 120
precio_teclado_con_descuento = precio_teclado * 0.90
precio_teclado_final = precio_teclado_con_descuento * 1.16
# Después: Una función reutilizable
def calcular_precio_final(precio_original):
"""Máquina calculadora de precios del almacén"""
precio_con_descuento = precio_original * 0.90
precio_final = precio_con_descuento * 1.16
return precio_final
# Uso simple y confiable
precio_laptop_final = calcular_precio_final(1500)
precio_mouse_final = calcular_precio_final(35)
precio_teclado_final = calcular_precio_final(120)
🔧 Anatomía de una función
La palabra clave def
Como en nuestro almacén necesitamos definir las especificaciones de cada máquina antes de construirla, en Python usamos def para definir una función:
def nombre_de_la_funcion():
"""Documentación de lo que hace la máquina"""
# Código que ejecuta la máquina
pass
Partes esenciales de una función
def procesar_pedido(codigo_producto, cantidad):
"""
Procesa un pedido en el almacén.
Args:
codigo_producto (str): Código único del producto
cantidad (int): Cantidad solicitada
Returns:
dict: Información del pedido procesado
"""
# 1. Validar que el producto existe
if not codigo_producto.startswith("PROD"):
return {"error": "Código de producto inválido"}
# 2. Verificar stock disponible
stock_actual = consultar_stock(codigo_producto)
if stock_actual < cantidad:
return {"error": "Stock insuficiente"}
# 3. Procesar el pedido
precio_unitario = obtener_precio(codigo_producto)
total = precio_unitario * cantidad
# 4. Retornar el resultado
return {
"codigo": codigo_producto,
"cantidad": cantidad,
"total": total,
"status": "procesado"
}
Análisis de las partes:
def- Palabra clave para definir la funciónprocesar_pedido- Nombre descriptivo de la función(codigo_producto, cantidad)- Parámetros de entrada"""docstring"""- Documentación de la función- Cuerpo de la función - El código que se ejecuta
return- Valor que devuelve la función
🏗️ Creando tu primera función
Función básica sin parámetros
def saludar_empleados():
"""Función que saluda a los empleados del almacén"""
print("¡Buenos días, equipo del almacén!")
print("¡Listos para un día productivo!")
# Llamar (usar) la función
saludar_empleados()
Salida:
¡Buenos días, equipo del almacén!
¡Listos para un día productivo!
Función con un parámetro
def calcular_area_zona(longitud):
"""Calcula el área de una zona cuadrada del almacén"""
area = longitud ** 2
print(f"El área de la zona es: {area} metros cuadrados")
# Usar la función
calcular_area_zona(10) # Área de 100 m²
calcular_area_zona(25) # Área de 625 m²
Función con múltiples parámetros
def generar_etiqueta_producto(nombre, precio, categoria, en_oferta=False):
"""Genera una etiqueta de precio para un producto"""
etiqueta = f"🏷️ {nombre}\n"
etiqueta += f"💰 Precio: ${precio:.2f}\n"
etiqueta += f"📂 Categoría: {categoria}\n"
if en_oferta:
etiqueta += "🔥 ¡EN OFERTA!"
print(etiqueta)
# Ejemplos de uso
generar_etiqueta_producto("Laptop Gaming", 1500.00, "Electrónicos")
generar_etiqueta_producto("Mouse Inalámbrico", 35.99, "Accesorios", True)
📊 Funciones que retornan valores
Diferencia entre print y return
# Función que IMPRIME (no retorna)
def mostrar_descuento(precio, porcentaje):
"""Muestra el descuento pero no retorna nada útil"""
descuento = precio * (porcentaje / 100)
print(f"Descuento: ${descuento:.2f}")
# No tiene return, por lo que retorna None implícitamente
# Función que RETORNA (más útil)
def calcular_descuento(precio, porcentaje):
"""Calcula y retorna el valor del descuento"""
descuento = precio * (porcentaje / 100)
return descuento
# Comparación de uso
mostrar_descuento(100, 15) # Imprime: Descuento: $15.00
resultado = mostrar_descuento(100, 15) # resultado = None (no útil)
descuento = calcular_descuento(100, 15) # descuento = 15.0 (útil!)
precio_final = 100 - descuento # Podemos usar el resultado
print(f"Precio final: ${precio_final:.2f}")
Función calculadora completa del almacén
def calcular_metricas_venta(precio_base, cantidad, descuento_porcentaje=0, impuesto_porcentaje=16):
"""
Calculadora completa de métricas de venta del almacén.
Args:
precio_base (float): Precio unitario del producto
cantidad (int): Cantidad de productos vendidos
descuento_porcentaje (float): Porcentaje de descuento (0-100)
impuesto_porcentaje (float): Porcentaje de impuesto (0-100)
Returns:
dict: Diccionario con todas las métricas calculadas
"""
# Cálculos paso a paso
subtotal = precio_base * cantidad
descuento = subtotal * (descuento_porcentaje / 100)
subtotal_con_descuento = subtotal - descuento
impuesto = subtotal_con_descuento * (impuesto_porcentaje / 100)
total_final = subtotal_con_descuento + impuesto
# Retornar todas las métricas
return {
"subtotal": subtotal,
"descuento": descuento,
"subtotal_con_descuento": subtotal_con_descuento,
"impuesto": impuesto,
"total_final": total_final,
"ahorro_cliente": descuento
}
# Ejemplo de uso
venta = calcular_metricas_venta(precio_base=50, cantidad=3, descuento_porcentaje=10)
print(f"📊 RESUMEN DE VENTA")
print(f"Subtotal: ${venta['subtotal']:.2f}")
print(f"Descuento: ${venta['descuento']:.2f}")
print(f"Impuesto: ${venta['impuesto']:.2f}")
print(f"Total: ${venta['total_final']:.2f}")
print(f"Ahorro del cliente: ${venta['ahorro_cliente']:.2f}")
🎨 Mejores prácticas para crear funciones
1. Nombres descriptivos y claros
# ❌ Nombres poco descriptivos
def calc(x, y):
return x * y * 0.16
def proc(data):
# ¿Qué procesa? ¿Cómo?
pass
# ✅ Nombres descriptivos
def calcular_impuesto_venta(precio_base, cantidad):
"""Calcula el impuesto de una venta basado en precio y cantidad"""
return precio_base * cantidad * 0.16
def procesar_devolucion_producto(producto_info):
"""Procesa la devolución de un producto al inventario"""
pass
2. Funciones pequeñas con una responsabilidad
# ❌ Función que hace demasiadas cosas
def procesar_pedido_completo(codigo, cantidad, cliente):
# Validar producto
# Verificar stock
# Calcular precios
# Procesar pago
# Actualizar inventario
# Enviar email
# Generar factura
# Actualizar estadísticas
pass # ¡Demasiadas responsabilidades!
# ✅ Funciones especializadas
def validar_producto(codigo):
"""Se enfoca solo en validar si un producto es válido"""
return codigo.startswith("PROD") and len(codigo) == 8
def verificar_stock_disponible(codigo, cantidad_solicitada):
"""Se enfoca solo en verificar stock"""
stock_actual = obtener_stock(codigo)
return stock_actual >= cantidad_solicitada
def calcular_precio_total(codigo, cantidad):
"""Se enfoca solo en calcular precios"""
precio_unitario = obtener_precio(codigo)
return precio_unitario * cantidad
3. Documentación clara con docstrings
def gestionar_inventario_automatico(productos, umbral_minimo=10):
"""
Gestiona automáticamente el inventario basado en umbrales mínimos.
Esta función revisa todos los productos en el inventario y genera
órdenes de recompra automáticas para aquellos productos cuyo stock
está por debajo del umbral especificado.
Args:
productos (list): Lista de diccionarios con información de productos.
Cada producto debe tener las claves: 'codigo', 'nombre', 'stock'
umbral_minimo (int, opcional): Stock mínimo antes de generar reorden.
Por defecto es 10.
Returns:
dict: Resultado del procesamiento con las siguientes claves:
- 'productos_procesados': Número total de productos revisados
- 'reordenes_generadas': Número de órdenes de recompra creadas
- 'productos_criticos': Lista de productos con stock crítico
Raises:
ValueError: Si la lista de productos está vacía o mal formateada
TypeError: Si umbral_minimo no es un número entero
Example:
>>> productos = [
... {'codigo': 'PROD001', 'nombre': 'Laptop', 'stock': 5},
... {'codigo': 'PROD002', 'nombre': 'Mouse', 'stock': 15}
... ]
>>> resultado = gestionar_inventario_automatico(productos, 8)
>>> print(resultado['reordenes_generadas'])
1
"""
# Implementación de la función...
pass
🔄 Funciones recursivas: Máquinas que se llaman a sí mismas
Algunas máquinas en nuestro almacén necesitan usar versiones más pequeñas de sí mismas. Por ejemplo, una máquina que cuenta todos los elementos en cajas que pueden contener otras cajas:
def contar_elementos_totales(contenedor):
"""
Cuenta todos los elementos en un contenedor que puede tener sub-contenedores.
Args:
contenedor (list): Lista que puede contener números o otras listas
Returns:
int: Número total de elementos contados
"""
total = 0
for elemento in contenedor:
if isinstance(elemento, list): # Si es una sub-caja
# La máquina se llama a sí misma para contar la sub-caja
total += contar_elementos_totales(elemento)
else: # Si es un elemento individual
total += 1
return total
# Ejemplo de almacén con estructura anidada
almacen_principal = [
"producto1",
"producto2",
["sub_caja1", "sub_caja2", ["caja_pequena1", "caja_pequena2"]],
"producto3",
["otra_subcaja"]
]
total_productos = contar_elementos_totales(almacen_principal)
print(f"Total de productos en el almacén: {total_productos}")
# Resultado: 7 productos
🚀 Funciones lambda: Máquinas portátiles
Para tareas muy simples, Python permite crear mini-máquinas portátiles llamadas funciones lambda:
# Función tradicional
def aplicar_descuento_standard(precio):
return precio * 0.90
# Función lambda equivalente (para casos simples)
aplicar_descuento = lambda precio: precio * 0.90
# Uso práctico con listas de productos
precios = [100, 250, 75, 400, 150]
# Aplicar descuento a todos los precios
precios_con_descuento = list(map(lambda precio: precio * 0.90, precios))
print(f"Precios originales: {precios}")
print(f"Precios con descuento: {precios_con_descuento}")
# Filtrar productos caros (más de $200)
productos_premium = list(filter(lambda precio: precio > 200, precios))
print(f"Productos premium: {productos_premium}")
🏭 Proyecto práctico: Sistema de gestión de productos
Vamos a crear un sistema completo con múltiples funciones especializadas:
# Base de datos simulada de productos
productos_almacen = [
{"codigo": "LAP001", "nombre": "Laptop Gaming", "precio": 1500, "stock": 5, "categoria": "Electronica"},
{"codigo": "MOU001", "nombre": "Mouse Inalámbrico", "precio": 35, "stock": 20, "categoria": "Accesorios"},
{"codigo": "TEC001", "nombre": "Teclado Mecánico", "precio": 120, "stock": 8, "categoria": "Accesorios"},
{"codigo": "MON001", "nombre": "Monitor 4K", "precio": 350, "stock": 3, "categoria": "Electronica"}
]
def buscar_producto_por_codigo(codigo):
"""Busca un producto específico por su código"""
for producto in productos_almacen:
if producto["codigo"] == codigo:
return producto
return None
def calcular_valor_total_categoria(categoria):
"""Calcula el valor total de inventario de una categoría"""
valor_total = 0
for producto in productos_almacen:
if producto["categoria"] == categoria:
valor_total += producto["precio"] * producto["stock"]
return valor_total
def generar_reporte_stock_bajo(umbral=10):
"""Genera reporte de productos con stock bajo"""
productos_criticos = []
for producto in productos_almacen:
if producto["stock"] <= umbral:
productos_criticos.append({
"codigo": producto["codigo"],
"nombre": producto["nombre"],
"stock_actual": producto["stock"],
"urgencia": "CRÍTICO" if producto["stock"] <= 5 else "BAJO"
})
return productos_criticos
def procesar_venta(codigo_producto, cantidad):
"""Procesa una venta y actualiza el inventario"""
producto = buscar_producto_por_codigo(codigo_producto)
if not producto:
return {"error": "Producto no encontrado"}
if producto["stock"] < cantidad:
return {"error": f"Stock insuficiente. Disponible: {producto['stock']}"}
# Actualizar stock
producto["stock"] -= cantidad
total_venta = producto["precio"] * cantidad
return {
"venta_exitosa": True,
"producto": producto["nombre"],
"cantidad_vendida": cantidad,
"total": total_venta,
"stock_restante": producto["stock"]
}
# Ejemplo de uso del sistema
print("=== SISTEMA DE GESTIÓN DE ALMACÉN ===")
# Buscar un producto
laptop = buscar_producto_por_codigo("LAP001")
print(f"Producto encontrado: {laptop['nombre']} - ${laptop['precio']}")
# Calcular valor por categoría
valor_electronica = calcular_valor_total_categoria("Electronica")
print(f"Valor total en Electrónica: ${valor_electronica}")
# Generar reporte de stock
productos_criticos = generar_reporte_stock_bajo(umbral=8)
print(f"Productos con stock crítico:")
for producto in productos_criticos:
print(f" - {producto['nombre']}: {producto['stock_actual']} unidades ({producto['urgencia']})")
# Procesar una venta
resultado_venta = procesar_venta("LAP001", 2)
if resultado_venta.get("venta_exitosa"):
print(f"Venta procesada: {resultado_venta['cantidad_vendida']} x {resultado_venta['producto']}")
print(f"Total: ${resultado_venta['total']}")
print(f"Stock restante: {resultado_venta['stock_restante']}")
🎯 Comprueba tu comprensión
Ejercicio 1: Función básica
Crea una función llamada calcular_capacidad_estante que reciba la altura, ancho y profundidad de un estante y retorne su volumen en metros cúbicos.
def calcular_capacidad_estante(altura, ancho, profundidad):
# Tu código aquí
pass
# Prueba tu función
volumen = calcular_capacidad_estante(2.5, 1.2, 0.8)
print(f"Capacidad del estante: {volumen} m³")
Ejercicio 2: Función con validación
Crea una función llamada validar_codigo_producto que reciba un código de producto y verifique que:
- Tenga exactamente 6 caracteres
- Los primeros 3 sean letras mayúsculas
- Los últimos 3 sean números
def validar_codigo_producto(codigo):
# Tu código aquí
pass
# Pruebas
print(validar_codigo_producto("LAP001")) # Debería ser True
print(validar_codigo_producto("lap001")) # Debería ser False
print(validar_codigo_producto("LAPTOP1")) # Debería ser False
Ejercicio 3: Función de procesamiento
Crea una función llamada procesar_lista_precios que reciba una lista de precios y un porcentaje de descuento, y retorne una nueva lista con los precios con descuento aplicado.
def procesar_lista_precios(precios, descuento_porcentaje):
# Tu código aquí
pass
# Prueba
precios_originales = [100, 250, 75, 400]
precios_rebajados = procesar_lista_precios(precios_originales, 15)
print(f"Precios rebajados: {precios_rebajados}")
💡 Consejos para el éxito
- Piensa en funciones como herramientas: Cada función debe tener un propósito específico y claro
- Reutilización es clave: Si escribes el mismo código más de 2 veces, crea una función
- Nombres descriptivos: El nombre debe explicar qué hace la función sin necesidad de leer el código
- Documenta siempre: Usa docstrings para explicar propósito, parámetros y valor de retorno
- Funciones pequeñas: Es mejor tener muchas funciones pequeñas que pocas funciones grandes
- Prueba tu código: Siempre verifica que tus funciones funcionen con diferentes valores de entrada
🎉 ¡Felicitaciones!
Has aprendido a crear máquinas especializadas (funciones) para tu almacén digital. Estas herramientas te permitirán:
- ✅ Automatizar tareas repetitivas
- ✅ Organizar mejor tu código
- ✅ Reducir errores y bugs
- ✅ Hacer tu código más legible y mantenible
- ✅ Crear soluciones escalables
En la siguiente sección aprenderemos sobre parámetros y argumentos: cómo hacer que nuestras máquinas sean más flexibles y potentes.
🧭 Navegación:
- Anterior: Funciones – Bloques de Construcción para Reutilización
- Siguiente: Parámetros y argumentos