Ir al contenido

Funciones en Python - De lo Básico a lo Avanzado

Publicado: a las  08:11 p. m.

Funciones en Python - De lo Básico a lo Avanzado

Funciones en Python

🎯 ¿Qué son las funciones?

Imaginate que estás en la cocina preparando tu comida favorita. Para hacer la salsa, siempre seguís los mismos pasos: picar cebolla, sofreír, agregar tomate, condimentar. Las funciones son exactamente eso: recetas de código que podés usar una y otra vez.

Definición formal

Una función es un bloque de código reutilizable que realiza una tarea específica. Tiene:

Analogía del mundo real

Función: Hacer mate
Entrada (parámetros): Yerba, agua caliente
Proceso: Llenar mate, poner bombilla, cebar
Salida (retorno): Mate listo para tomar

🚀 ¿Por qué usar funciones?

1. Evitar repetir código (DRY - Don’t Repeat Yourself)

Sin funciones:

# Calcular área de rectángulo 1
base1 = 10
altura1 = 5
area1 = base1 * altura1
print(f"Área 1: {area1}")

# Calcular área de rectángulo 2
base2 = 8
altura2 = 3
area2 = base2 * altura2
print(f"Área 2: {area2}")

# Calcular área de rectángulo 3
base3 = 15
altura3 = 7
area3 = base3 * altura3
print(f"Área 3: {area3}")

Con funciones:

def calcular_area_rectangulo(base, altura):
    return base * altura

area1 = calcular_area_rectangulo(10, 5)
area2 = calcular_area_rectangulo(8, 3)
area3 = calcular_area_rectangulo(15, 7)

print(f"Área 1: {area1}")
print(f"Área 2: {area2}")
print(f"Área 3: {area3}")

2. Organizar el código

Las funciones dividen tu programa en partes manejables, como capítulos de un libro.

3. Reutilización

Escribís una vez, usás mil veces.

4. Facilitar el trabajo en equipo

Cada persona puede trabajar en funciones diferentes.


📝 Crear tu primera función

Estructura básica

def nombre_funcion(parametro1, parametro2):
    """
    Docstring: Descripción de qué hace la función
    """
    # Código de la función
    resultado = parametro1 + parametro2
    return resultado

Componentes:

  1. def: Palabra clave para definir una función
  2. nombre_funcion: Nombre descriptivo (usa snake_case)
  3. (parametros): Datos que recibe (opcional)
  4. """ docstring """: Documentación (opcional pero recomendado)
  5. Cuerpo: El código indentado
  6. return: Valor que devuelve (opcional)

Ejemplo simple

def saludar(nombre):
    """
    Saluda a una persona por su nombre
    """
    mensaje = f"¡Hola, {nombre}! ¿Cómo estás?"
    return mensaje

# Usar la función
saludo1 = saludar("Juan")
saludo2 = saludar("María")

print(saludo1)  # ¡Hola, Juan! ¿Cómo estás?
print(saludo2)  # ¡Hola, María! ¿Cómo estás?

🔧 Parámetros y argumentos

Parámetros vs Argumentos

def sumar(a, b):  # a y b son PARÁMETROS
    return a + b

resultado = sumar(5, 3)  # 5 y 3 son ARGUMENTOS

Tipos de parámetros

1. Parámetros posicionales

def presentar_persona(nombre, edad, ciudad):
    return f"{nombre} tiene {edad} años y vive en {ciudad}"

# El orden importa
print(presentar_persona("Ana", 25, "El Calafate"))
# Ana tiene 25 años y vive en El Calafate

2. Parámetros con nombre (keyword arguments)

# Podés especificar el nombre del parámetro
print(presentar_persona(ciudad="El Calafate", nombre="Ana", edad=25))
# El orden no importa cuando usás nombres

3. Parámetros con valores por defecto

def configurar_sensor(id_sensor, temp_min=0, temp_max=100):
    """
    Configura un sensor con valores por defecto
    """
    return {
        'id': id_sensor,
        'temp_min': temp_min,
        'temp_max': temp_max
    }

# Usar valores por defecto
sensor1 = configurar_sensor("TEMP-001")
print(sensor1)  # {'id': 'TEMP-001', 'temp_min': 0, 'temp_max': 100}

# Sobrescribir valores por defecto
sensor2 = configurar_sensor("TEMP-002", temp_min=15, temp_max=85)
print(sensor2)  # {'id': 'TEMP-002', 'temp_min': 15, 'temp_max': 85}

4. Número variable de argumentos (*args)

def calcular_promedio(*numeros):
    """
    Calcula el promedio de cualquier cantidad de números
    """
    if len(numeros) == 0:
        return 0
    return sum(numeros) / len(numeros)

# Podés pasar cualquier cantidad de argumentos
print(calcular_promedio(8, 7, 9))           # 8.0
print(calcular_promedio(10, 9, 8, 7, 6))    # 8.0
print(calcular_promedio(5))                  # 5.0

5. Argumentos con nombre variables (**kwargs)

def crear_reporte(**datos):
    """
    Crea un reporte con datos variables
    """
    print("📊 REPORTE")
    print("=" * 40)
    for clave, valor in datos.items():
        print(f"{clave}: {valor}")

# Podés pasar cualquier cantidad de pares clave-valor
crear_reporte(
    temperatura=85.5,
    presion=7.2,
    nivel=3.8,
    estado="NORMAL"
)

🔄 Return: Devolver valores

Función sin return

def imprimir_mensaje(texto):
    """
    Solo imprime, no devuelve nada
    """
    print(f"Mensaje: {texto}")

resultado = imprimir_mensaje("Hola")
print(resultado)  # None

Función con return

def multiplicar(a, b):
    """
    Devuelve el producto de dos números
    """
    return a * b

resultado = multiplicar(5, 3)
print(resultado)  # 15

Return múltiple (tupla)

def calcular_estadisticas(numeros):
    """
    Devuelve mínimo, máximo y promedio
    """
    minimo = min(numeros)
    maximo = max(numeros)
    promedio = sum(numeros) / len(numeros)

    return minimo, maximo, promedio

# Desempaquetar los valores
min_val, max_val, prom = calcular_estadisticas([10, 20, 30, 40, 50])
print(f"Mín: {min_val}, Máx: {max_val}, Prom: {prom}")

Return temprano

def verificar_temperatura(temp):
    """
    Verifica si la temperatura está en rango
    """
    if temp < 0:
        return "❌ Temperatura muy baja"

    if temp > 100:
        return "❌ Temperatura muy alta"

    return "✅ Temperatura normal"

print(verificar_temperatura(-5))   # ❌ Temperatura muy baja
print(verificar_temperatura(50))   # ✅ Temperatura normal
print(verificar_temperatura(150))  # ❌ Temperatura muy alta

🌍 Alcance de variables (Scope)

Variables locales

def calcular_area(base, altura):
    area = base * altura  # 'area' es LOCAL a esta función
    return area

resultado = calcular_area(10, 5)
# print(area)  # ❌ Error: 'area' no existe fuera de la función

Variables globales

temperatura_maxima = 100  # Variable GLOBAL

def verificar_temperatura(temp):
    # Podemos LEER variables globales
    if temp > temperatura_maxima:
        return "Temperatura alta"
    return "Temperatura normal"

print(verificar_temperatura(85))  # Temperatura normal

Modificar variables globales

contador = 0  # Variable global

def incrementar_contador():
    global contador  # Declarar que vamos a modificar la global
    contador += 1

incrementar_contador()
incrementar_contador()
print(contador)  # 2

⚠️ Consejo: Evitá usar global cuando sea posible. Es mejor pasar y retornar valores.


🏭 Ejemplos industriales prácticos

Ejemplo 1: Control de temperatura

def controlar_temperatura(temp_actual, temp_objetivo, tolerancia=2):
    """
    Determina la acción a tomar según la temperatura

    Args:
        temp_actual: Temperatura medida
        temp_objetivo: Temperatura deseada
        tolerancia: Margen de error permitido

    Returns:
        str: Acción a realizar
    """
    diferencia = temp_actual - temp_objetivo

    if abs(diferencia) <= tolerancia:
        return "✅ MANTENER - Temperatura óptima"
    elif diferencia > 0:
        return f"🔽 ENFRIAR - {diferencia}°C por encima"
    else:
        return f"🔼 CALENTAR - {abs(diferencia)}°C por debajo"

# Uso
print(controlar_temperatura(75, 75))      # MANTENER
print(controlar_temperatura(80, 75))      # ENFRIAR
print(controlar_temperatura(70, 75))      # CALENTAR

Ejemplo 2: Validación de sensores

def validar_lectura_sensor(valor, min_valido, max_valido):
    """
    Valida si una lectura de sensor está en rango

    Returns:
        tuple: (es_valido, mensaje)
    """
    if valor < min_valido:
        return False, f"Valor muy bajo: {valor} < {min_valido}"

    if valor > max_valido:
        return False, f"Valor muy alto: {valor} > {max_valido}"

    return True, "Lectura válida"

# Uso
valido, mensaje = validar_lectura_sensor(85, 0, 100)
print(f"{mensaje} - Válido: {valido}")

Ejemplo 3: Cálculo de consumo energético

def calcular_consumo_energia(potencia_watts, horas_uso, precio_kwh=0.15):
    """
    Calcula el consumo y costo de energía

    Args:
        potencia_watts: Potencia del dispositivo en watts
        horas_uso: Horas de uso
        precio_kwh: Precio por kWh (default: $0.15)

    Returns:
        dict: Consumo en kWh y costo
    """
    consumo_kwh = (potencia_watts * horas_uso) / 1000
    costo = consumo_kwh * precio_kwh

    return {
        'consumo_kwh': round(consumo_kwh, 2),
        'costo': round(costo, 2),
        'horas': horas_uso
    }

# Motor de 1500W funcionando 8 horas
resultado = calcular_consumo_energia(1500, 8)
print(f"Consumo: {resultado['consumo_kwh']} kWh")
print(f"Costo: ${resultado['costo']}")

🎨 Funciones lambda (avanzado - 4to año)

Las funciones lambda son funciones anónimas de una sola línea.

Sintaxis

# Función normal
def cuadrado(x):
    return x ** 2

# Función lambda equivalente
cuadrado_lambda = lambda x: x ** 2

print(cuadrado(5))         # 25
print(cuadrado_lambda(5))  # 25

Uso con map, filter, sorted

# map: Aplicar función a cada elemento
numeros = [1, 2, 3, 4, 5]
cuadrados = list(map(lambda x: x**2, numeros))
print(cuadrados)  # [1, 4, 9, 16, 25]

# filter: Filtrar elementos
pares = list(filter(lambda x: x % 2 == 0, numeros))
print(pares)  # [2, 4]

# sorted: Ordenar con clave personalizada
sensores = [
    {'id': 'TEMP-001', 'valor': 85},
    {'id': 'TEMP-002', 'valor': 72},
    {'id': 'TEMP-003', 'valor': 91}
]

ordenados = sorted(sensores, key=lambda s: s['valor'])
for sensor in ordenados:
    print(f"{sensor['id']}: {sensor['valor']}")

📚 Funciones predefinidas útiles

Funciones matemáticas y numéricas

# abs: Valor absoluto
print(abs(-10))  # 10

# round: Redondear
print(round(3.14159, 2))  # 3.14

# pow: Potencia
print(pow(2, 3))  # 8

# sum: Suma de elementos
print(sum([1, 2, 3, 4, 5]))  # 15

# min, max
print(min([5, 2, 8, 1]))  # 1
print(max([5, 2, 8, 1]))  # 8

Funciones de conversión

# int, float, str
print(int("42"))      # 42
print(float("3.14"))  # 3.14
print(str(100))       # "100"

# list, tuple, set
print(list("abc"))    # ['a', 'b', 'c']
print(tuple([1, 2]))  # (1, 2)
print(set([1, 1, 2])) # {1, 2}

Funciones para strings

texto = "Hola Mundo"

print(texto.upper())      # HOLA MUNDO
print(texto.lower())      # hola mundo
print(texto.title())      # Hola Mundo
print(texto.replace("Hola", "Chau"))  # Chau Mundo
print(texto.split())      # ['Hola', 'Mundo']
print("-".join(['a', 'b', 'c']))  # a-b-c

Funciones para listas

lista = [3, 1, 4, 1, 5]

lista.append(9)       # Agregar al final
lista.remove(1)       # Eliminar primera ocurrencia
lista.sort()          # Ordenar
lista.reverse()       # Invertir
print(lista.count(1)) # Contar ocurrencias
print(lista.index(4)) # Índice de elemento

🎯 Ejercicios prácticos

🟢 Nivel Básico (3er año)

Ejercicio 1: Creá una función que calcule el área de un círculo dado su radio.

# Fórmula: área = π * radio²
# Usá 3.14159 para π

Ejercicio 2: Creá una función que determine si un número es par o impar.

Ejercicio 3: Creá una función que convierta temperatura de Celsius a Fahrenheit.

# Fórmula: F = (C × 9/5) + 32

🟡 Nivel Medio (3er y 4to año)

Ejercicio 4: Creá una función que reciba una lista de números y devuelva solo los números pares.

Ejercicio 5: Creá una función que calcule el factorial de un número.

Ejercicio 6: Creá una función que valide si una contraseña es segura (mínimo 8 caracteres, al menos una mayúscula, un número).

🔴 Nivel Avanzado (4to año)

Ejercicio 7: Creá una función que reciba una lista de sensores (diccionarios) y devuelva los que tienen lecturas fuera de rango.

Ejercicio 8: Creá una función que use *args y **kwargs para crear un reporte flexible.

Ejercicio 9: Implementá una función recursiva que calcule la secuencia de Fibonacci.

Ejercicio 10: Creá una función que use lambda para ordenar una lista de diccionarios por múltiples criterios.


💡 Buenas prácticas

✅ Hacé esto:

  1. Nombres descriptivos: calcular_promedio() es mejor que calc()
  2. Una tarea por función: Cada función debe hacer una cosa bien
  3. Documentá con docstrings: Explicá qué hace, qué recibe, qué devuelve
  4. Usa type hints (Python 3.5+):
    def sumar(a: int, b: int) -> int:
        return a + b
  5. Validá los parámetros: Verificá que los datos sean correctos
  6. Retorná valores: Mejor que modificar variables globales

❌ Evitá esto:

  1. Funciones muy largas: Si tiene más de 50 líneas, dividila
  2. Muchos parámetros: Más de 5 parámetros es confuso
  3. Efectos secundarios ocultos: La función no debería modificar cosas inesperadas
  4. Nombres genéricos: hacer_cosas(), procesar() no dicen nada

🐛 Errores comunes

Error 1: Olvidar el return

# ❌ Mal
def sumar(a, b):
    resultado = a + b
    # Falta return!

print(sumar(5, 3))  # None

# ✅ Bien
def sumar(a, b):
    return a + b

print(sumar(5, 3))  # 8

Error 2: Modificar parámetros mutables

# ❌ Mal
def agregar_elemento(elemento, lista=[]):
    lista.append(elemento)
    return lista

print(agregar_elemento(1))  # [1]
print(agregar_elemento(2))  # [1, 2] ¡Sorpresa!

# ✅ Bien
def agregar_elemento(elemento, lista=None):
    if lista is None:
        lista = []
    lista.append(elemento)
    return lista

Error 3: Confundir parámetros posicionales

def dividir(dividendo, divisor):
    return dividendo / divisor

# ❌ Mal (orden incorrecto)
print(dividir(2, 10))  # 0.2

# ✅ Bien
print(dividir(10, 2))  # 5.0
# O usar nombres
print(dividir(divisor=2, dividendo=10))  # 5.0

🎓 Resumen

Funciones: Bloques de código reutilizables

Parámetros: Datos que recibe la función

Return: Valor que devuelve la función

Scope: Alcance de las variables (local vs global)

Lambda: Funciones anónimas de una línea (4to año)

Buenas prácticas: Nombres claros, una tarea por función, documentación


🚀 Próximos pasos

Para 3er año:

  1. Practicá creando funciones simples
  2. Resolvé los ejercicios básicos y medios
  3. Experimentá con parámetros y return

Para 4to año:

  1. Dominá funciones lambda
  2. Practicá con *args y **kwargs
  3. Aprendé sobre decoradores
  4. Resolvé los ejercicios avanzados

¿Tenés dudas? ¡Preguntá en clase! 🙋‍♂️

¡Ahora a crear funciones increíbles! 💪🐍