Introducción
Contenido de la lección.
Objetivos de aprendizaje
- Objetivo 1
- Objetivo 2
- Objetivo 3
Objetivos de Aprendizaje
Al finalizar este tema, serás capaz de:
- Comprender la sintaxis y estructura de las funciones en Python
- Dominar el uso de parámetros posicionales, nombrados y con valores por defecto
- Aplicar el statement return para devolver valores y controlar el flujo de ejecución
- Implementar funciones para resolver problemas reales de ingeniería
📚 1. Conceptos Fundamentales de Funciones
Una función en Python es un bloque de código que se ejecuta cuando es llamada. Las funciones se definen usando la palabra clave 'def', seguida del nombre de la función y paréntesis. Los parámetros se colocan dentro de los paréntesis, y el cuerpo de la función se indenta. El statement 'return' permite devolver un valor al código que llamó la función. Las funciones proporcionan modularidad, reutilización de código y abstracción, elementos clave en el desarrollo de software profesional. En ingeniería, las funciones nos permiten encapsular algoritmos, cálculos matemáticos y lógica de negocio de manera organizada y eficiente.
def saludar():
print('Hola desde la función')
return 'Saludo completado'
# Llamada a la función
resultado = saludar()
print(f'Resultado: {resultado}')
Hola desde la función Resultado: Saludo completado
def calcular_area_rectangulo(largo, ancho):
area = largo * ancho
return area
# Llamadas con argumentos posicionales
area1 = calcular_area_rectangulo(5, 3)
area2 = calcular_area_rectangulo(10, 7)
print(f'Área 1: {area1} m²')
print(f'Área 2: {area2} m²')
Área 1: 15 m² Área 2: 70 m²
🎯 2. Parámetros Nombrados y Valores Por Defecto
Los parámetros nombrados (keyword arguments) permiten pasar argumentos especificando el nombre del parámetro, independientemente del orden. Los valores por defecto se asignan a parámetros cuando no se proporciona un argumento específico. Esta flexibilidad es especialmente útil en funciones con múltiples parámetros opcionales, común en aplicaciones de ingeniería donde se requiere configurar múltiples variables. Los parámetros con valores por defecto deben aparecer después de los parámetros obligatorios en la definición de la función.
def calcular_potencia_electrica(voltaje, corriente, factor_potencia=1.0):
potencia = voltaje * corriente * factor_potencia
return potencia
# Diferentes formas de llamar la función
p1 = calcular_potencia_electrica(220, 5)
p2 = calcular_potencia_electrica(voltaje=110, corriente=8, factor_potencia=0.85)
p3 = calcular_potencia_electrica(corriente=3, voltaje=240)
print(f'Potencia 1: {p1} W')
print(f'Potencia 2: {p2} W')
print(f'Potencia 3: {p3} W')
Potencia 1: 1100.0 W Potencia 2: 748.0 W Potencia 3: 720.0 W
def configurar_sensor(tipo='temperatura', rango_min=0, rango_max=100, unidad='°C'):
config = {
'tipo': tipo,
'rango': (rango_min, rango_max),
'unidad': unidad
}
return config
# Diferentes configuraciones
sensor1 = configurar_sensor()
sensor2 = configurar_sensor('presión', 0, 1000, 'Pa')
sensor3 = configurar_sensor(tipo='humedad', rango_max=100, unidad='%')
print(f'Sensor 1: {sensor1}')
print(f'Sensor 2: {sensor2}')
print(f'Sensor 3: {sensor3}')
Sensor 1: {'tipo': 'temperatura', 'rango': (0, 100), 'unidad': '°C'} Sensor 2: {'tipo': 'presión', 'rango': (0, 1000), 'unidad': 'Pa'} Sensor 3: {'tipo': 'humedad', 'rango': (0, 100), 'unidad': '%'}
💡 3. Return y Control de Flujo
El statement 'return' no solo permite devolver valores, sino también controlar el flujo de ejecución de la función. Una función puede tener múltiples returns, retornar diferentes tipos de datos, o incluso múltiples valores simultáneamente. Cuando se ejecuta un return, la función termina inmediatamente. Si no se especifica return, la función devuelve None por defecto. En ingeniería, esto es útil para validar entradas, manejar casos especiales, y implementar lógica condicional compleja en algoritmos de control y procesamiento de datos.
def clasificar_resistencia(valor_ohms):
if valor_ohms <= 0:
return 'Error: Valor inválido'
elif valor_ohms < 1000:
return f'{valor_ohms} Ω - Baja resistencia'
elif valor_ohms < 1000000:
return f'{valor_ohms/1000} kΩ - Resistencia media'
else:
return f'{valor_ohms/1000000} MΩ - Alta resistencia'
# Pruebas con diferentes valores
valores = [-100, 470, 4700, 2200000]
for valor in valores:
resultado = clasificar_resistencia(valor)
print(resultado)
Error: Valor inválido 470 Ω - Baja resistencia 4.7 kΩ - Resistencia media 2.2 MΩ - Alta resistencia
def analizar_circuito(voltaje, resistencia):
if resistencia == 0:
return None, None, 'Error: División por cero'
corriente = voltaje / resistencia
potencia = voltaje * corriente
return corriente, potencia, 'Cálculo exitoso'
# Análisis de circuito
I, P, estado = analizar_circuito(12, 4)
print(f'Corriente: {I} A')
print(f'Potencia: {P} W')
print(f'Estado: {estado}')
# Caso de error
I2, P2, estado2 = analizar_circuito(12, 0)
print(f'\nError - Estado: {estado2}')
Corriente: 3.0 A Potencia: 36.0 W Estado: Cálculo exitoso Error - Estado: Error: División por cero
🔧 4. Casos de Uso Avanzados en Ingeniería
Las funciones en Python pueden implementar algoritmos complejos utilizados en ingeniería, como procesamiento de señales, análisis estadístico, y optimización. Los parámetros pueden incluir listas, diccionarios y funciones como argumentos, permitiendo crear soluciones flexibles y escalables. Es importante considerar la documentación de funciones usando docstrings, el manejo de excepciones, y la optimización del rendimiento. En proyectos profesionales, las funciones deben ser robustas, bien documentadas y fáciles de mantener.
def analizar_datos_sensor(datos, incluir_outliers=True):
if not datos:
return {'error': 'Lista vacía'}
# Cálculos estadísticos básicos
promedio = sum(datos) / len(datos)
maximo = max(datos)
minimo = min(datos)
# Detectar outliers (valores atípicos)
if not incluir_outliers:
q1 = sorted(datos)[len(datos)//4]
q3 = sorted(datos)[3*len(datos)//4]
iqr = q3 - q1
limite_inf = q1 - 1.5 * iqr
limite_sup = q3 + 1.5 * iqr
datos = [x for x in datos if limite_inf <= x <= limite_sup]
promedio = sum(datos) / len(datos) if datos else 0
return {
'promedio': round(promedio, 2),
'maximo': maximo,
'minimo': minimo,
'total_muestras': len(datos)
}
# Datos simulados de sensor de temperatura
temperaturas = [22.1, 23.5, 22.8, 24.2, 22.9, 35.7, 23.1, 22.6]
resultado1 = analizar_datos_sensor(temperaturas)
resultado2 = analizar_datos_sensor(temperaturas, incluir_outliers=False)
print('Con outliers:', resultado1)
print('Sin outliers:', resultado2)
Con outliers: {'promedio': 24.61, 'maximo': 35.7, 'minimo': 22.1, 'total_muestras': 8} Sin outliers: {'promedio': 23.03, 'maximo': 24.2, 'minimo': 22.1, 'total_muestras': 7}
def filtro_media_movil(señal, ventana=3, tipo='simple'):
if len(señal) < ventana:
return señal
señal_filtrada = []
for i in range(len(señal)):
if i < ventana - 1:
señal_filtrada.append(señal[i])
else:
if tipo == 'simple':
promedio = sum(señal[i-ventana+1:i+1]) / ventana
elif tipo == 'ponderado':
pesos = list(range(1, ventana+1))
suma_ponderada = sum(señal[j] * pesos[j-(i-ventana+1)]
for j in range(i-ventana+1, i+1))
promedio = suma_ponderada / sum(pesos)
señal_filtrada.append(round(promedio, 2))
return señal_filtrada
# Señal con ruido simulado
señal_original = [10, 12, 8, 15, 11, 20, 9, 14, 13, 16]
filtro_simple = filtro_media_movil(señal_original, 3, 'simple')
filtro_ponderado = filtro_media_movil(señal_original, 3, 'ponderado')
print('Original:', señal_original)
print('Filtro simple:', filtro_simple)
print('Filtro ponderado:', filtro_ponderado)
Original: [10, 12, 8, 15, 11, 20, 9, 14, 13, 16] Filtro simple: [10, 12, 10.0, 11.67, 11.33, 15.33, 13.33, 14.33, 12.0, 14.33] Filtro ponderado: [10, 12, 9.33, 12.5, 12.33, 16.83, 12.5, 14.5, 13.0, 14.83]
Ejercicios Prácticos
Calculadora de Eficiencia Energética
BÁSICODescripción:
Crear una función que calcule la eficiencia energética de un motor eléctrico. La función debe recibir potencia de entrada, potencia de salida, y opcionalmente el tipo de motor (AC/DC). Debe validar que las potencias sean positivas y que la eficiencia no supere el 100%.
Analizador de Frecuencias de Señal
INTERMEDIODescripción:
Desarrollar una función que analice una lista de valores de una señal digital y determine la frecuencia dominante, amplitud máxima y mínima. La función debe manejar listas vacías y permitir especificar el rango de frecuencias de interés.
Sistema de Control PID
AVANZADODescripción:
Implementar una función que simule un controlador PID (Proporcional-Integral-Derivativo). Debe recibir el error actual, errores anteriores, y los parámetros Kp, Ki, Kd. La función debe calcular y retornar la señal de control junto con los componentes P, I, D por separado.
Optimizador de Redes Eléctricas
AVANZADODescripción:
Crear una función que optimice la distribución de carga en una red eléctrica. Debe recibir un diccionario con nodos y sus capacidades, y retornar la distribución óptima minimizando las pérdidas. Incluir parámetros para diferentes algoritmos de optimización.
Resumen y Próximos Pasos
Las funciones son herramientas fundamentales que permiten escribir código modular, reutilizable y mantenible. Hemos explorado desde conceptos básicos como definición y parámetros, hasta técnicas avanzadas como el manejo de argumentos nombrados y retorno múltiple. En el próximo tema, profundizaremos en el ámbito de variables (scope) y las funciones lambda, conceptos esenciales para el desarrollo de aplicaciones más complejas y el paradigma de programación funcional en Python.