Lección Python

Contenido de la lección

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.

Función básica sin parámetros Copiar
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
Explicación: Esta función básica no recibe parámetros, ejecuta una acción (imprimir) y retorna un valor string que puede ser capturado y utilizado.
Función con parámetros posicionales Copiar
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²
Explicación: Los parámetros posicionales se pasan en el orden específico definido en la función. El orden de los argumentos al llamar la función debe coincidir con el orden de los parámetros.

🎯 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.

Función con parámetros nombrados y valores por defecto Copiar
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
Explicación: La función permite llamadas con argumentos posicionales, nombrados, y combinaciones de ambos. El factor_potencia tiene un valor por defecto de 1.0 para circuitos resistivos puros.
Función con múltiples valores por defecto Copiar
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': '%'}
Explicación: Esta función demuestra cómo los valores por defecto permiten crear configuraciones flexibles, útil en sistemas de instrumentación donde diferentes sensores requieren parámetros específicos.

💡 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.

Función con múltiples returns y validación Copiar
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
Explicación: La función utiliza múltiples returns para manejar diferentes casos y validaciones, común en sistemas de clasificación y análisis de componentes electrónicos.
Función que retorna múltiples valores Copiar
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
Explicación: Esta función demuestra el retorno múltiple de valores, útil para devolver resultados de cálculos junto con información de estado o error.

🔧 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.

Función de análisis estadístico para datos de sensores Copiar
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}
Explicación: Esta función implementa análisis estadístico con detección de outliers, común en el procesamiento de datos de sensores industriales donde se requiere filtrar lecturas anómalas.
Función para diseño de filtros digitales Copiar
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]
Explicación: Implementación de filtros de media móvil para procesamiento de señales, fundamentales en sistemas de control y adquisición de datos para reducir ruido y suavizar señales.

Ejercicios Prácticos

Calculadora de Eficiencia Energética
BÁSICO

Descripció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%.

Pista: Eficiencia = (Potencia_salida / Potencia_entrada) * 100. Usa parámetros por defecto y validaciones con return temprano para casos de error.
Analizador de Frecuencias de Señal
INTERMEDIO

Descripció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.

Pista: Usa parámetros nombrados para los rangos de frecuencia. Implementa validación de entrada y retorna un diccionario con los resultados del análisis.
Sistema de Control PID
AVANZADO

Descripció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.

Pista: Usa listas para mantener el historial de errores. Implementa parámetros por defecto para las constantes PID y retorna múltiples valores para análisis detallado.
Optimizador de Redes Eléctricas
AVANZADO

Descripció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.

Pista: Usa diccionarios como parámetros y valores de retorno. Implementa diferentes estrategias de optimización usando parámetros nombrados para seleccionar el algoritmo.

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.

🏷️ Etiquetas:
python funciones parámetros return ingeniería programación