🐍 Funciones y Módulos

¿Qué es una función?

Una función es un bloque de código reutilizable que realiza una tarea específica. En Python se define con la palabra clave def.

def saludar():
    """Función simple que imprime un saludo."""
    print("¡Hola, mundo!")

# Llamar a la función
saludar()  # ¡Hola, mundo!

Funciones con parámetros

def saludar_persona(nombre):
    print(f"¡Hola, {nombre}!")

saludar_persona("Ana")     # ¡Hola, Ana!
saludar_persona("Carlos")  # ¡Hola, Carlos!

Parámetros con valor por defecto

def saludar(nombre, saludo="Hola"):
    print(f"{saludo}, {nombre}!")

saludar("Ana")             # Hola, Ana!
saludar("Ana", "Buenos días")  # Buenos días, Ana!
saludar(nombre="Luis", saludo="Hey")  # Argumentos nombrados

Valor de retorno (return)

def sumar(a, b):
    return a + b

resultado = sumar(5, 3)
print(resultado)  # 8

def operaciones(a, b):
    suma = a + b
    resta = a - b
    producto = a * b
    return suma, resta, producto  # Devuelve una tupla

s, r, p = operaciones(10, 3)
print(f"Suma: {s}, Resta: {r}, Producto: {p}")

Argumentos *args y **kwargs

A veces no sabes cuántos argumentos recibirás. *args captura argumentos posicionales como una tupla, y **kwargs captura argumentos nombrados como un diccionario.

def sumar_varios(*args):
    """Suma una cantidad variable de números."""
    total = 0
    for num in args:
        total += num
    return total

print(sumar_varios(1, 2, 3))        # 6
print(sumar_varios(10, 20, 30, 40)) # 100

def mostrar_info(**kwargs):
    """Muestra información recibida como clave=valor."""
    for clave, valor in kwargs.items():
        print(f"{clave}: {valor}")

mostrar_info(nombre="Ana", edad=25, ciudad="Madrid")
# nombre: Ana
# edad: 25
# ciudad: Madrid

def ejemplo_completo(nombre, *args, **kwargs):
    print(f"Nombre: {nombre}")
    print(f"Args: {args}")
    print(f"Kwargs: {kwargs}")

ejemplo_completo("Ana", 1, 2, 3, curso="Python", nota=9)
# Nombre: Ana
# Args: (1, 2, 3)
# Kwargs: {'curso': 'Python', 'nota': 9}

Funciones lambda (anónimas)

Una función lambda es una función pequeña y anónima que se define en una sola línea. Sintaxis: lambda argumentos: expresión

# Lambda que suma dos números
suma = lambda a, b: a + b
print(suma(3, 5))  # 8

# Lambda con sorted (ordenar por el segundo elemento)
puntos = [(1, 3), (4, 1), (2, 5)]
puntos.sort(key=lambda p: p[1])
print(puntos)  # [(4, 1), (1, 3), (2, 5)]

# Lambda con filter (filtrar pares)
numeros = [1, 2, 3, 4, 5, 6]
pares = list(filter(lambda x: x % 2 == 0, numeros))
print(pares)  # [2, 4, 6]

# Lambda con map (transformar)
cuadrados = list(map(lambda x: x ** 2, numeros))
print(cuadrados)  # [1, 4, 9, 16, 25, 36]

Módulos y import

Un módulo es un archivo .py que contiene funciones y variables que puedes reutilizar. Python incluye muchos módulos en su biblioteca estándar.

# Formas de importar
import math                    # Importa todo el módulo
print(math.sqrt(16))           # 4.0

from math import pi, sin       # Importa solo lo necesario
print(pi)                      # 3.141592653589793

from math import *             # Importa todo (⚠️ no recomendado, contamina espacio)

import math as m               # Alias
print(m.floor(3.7))            # 3

Módulo math

import math

print(math.pi)            # 3.141592653589793
print(math.e)             # 2.718281828459045
print(math.sqrt(25))      # 5.0
print(math.ceil(3.2))     # 4 (redondeo hacia arriba)
print(math.floor(3.8))    # 3 (redondeo hacia abajo)
print(math.factorial(5))  # 120
print(math.sin(math.pi/2)) # 1.0
print(math.pow(2, 10))    # 1024.0

Módulo random

import random

print(random.random())           # Aleatorio float entre 0.0 y 1.0
print(random.randint(1, 10))     # Entero aleatorio entre 1 y 10 (inclusive)
print(random.uniform(1, 10))     # Float aleatorio entre 1.0 y 10.0
print(random.choice(["rojo", "verde", "azul"]))  # Elemento aleatorio de una lista

lista = [1, 2, 3, 4, 5]
random.shuffle(lista)            # Barajar la lista (modifica original)
print(lista)

print(random.sample(range(50), 5))  # 5 números únicos aleatorios

Módulo datetime

import datetime

# Fecha y hora actual
ahora = datetime.datetime.now()
print(ahora)               # 2026-07-04 14:30:00.123456 (ejemplo)

# Fecha actual
hoy = datetime.date.today()
print(hoy)                 # 2026-07-04

# Crear fecha específica
fecha = datetime.date(2026, 12, 25)

# Diferencia entre fechas
navidad = datetime.date(2026, 12, 25)
dias_restantes = navidad - hoy
print(f"Faltan {dias_restantes.days} días para Navidad")

# Formatear fechas
print(ahora.strftime("%d/%m/%Y"))            # 04/07/2026
print(ahora.strftime("%d de %B de %Y"))      # 04 de julio de 2026
print(ahora.strftime("%H:%M:%S"))            # 14:30:00

Módulo os

import os

# Directorio actual
print(os.getcwd())  # /var/www/... (ruta actual)

# Listar archivos del directorio actual
print(os.listdir("."))

# Crear directorio
os.mkdir("nueva_carpeta")     # Crea un directorio
os.makedirs("a/b/c")          # Crea directorios anidados

# Eliminar
os.remove("archivo.txt")      # Elimina archivo
os.rmdir("nueva_carpeta")     # Elimina directorio vacío

# Comprobar existencia
print(os.path.exists("archivo.txt"))  # False
print(os.path.isfile("index.html"))   # True (si existe)
print(os.path.isdir("cursos"))        # True (si existe)

# Unir rutas de forma segura
ruta = os.path.join("carpeta", "subcarpeta", "archivo.txt")
print(ruta)  # carpeta/subcarpeta/archivo.txt (según sistema)

# Variables de entorno
print(os.getenv("HOME", "no definido"))  # /root

Crear tus propios módulos

Crea un archivo utilidades.py:

# utilidades.py
def saludar(nombre):
    return f"¡Hola, {nombre}!"

def sumar(a, b):
    return a + b

PI = 3.1416

Y úsalo desde otro archivo:

# main.py (en el mismo directorio)
import utilidades

print(utilidades.saludar("Ana"))     # ¡Hola, Ana!
print(utilidades.sumar(5, 3))        # 8
print(utilidades.PI)                 # 3.1416

from utilidades import saludar, PI
print(saludar("Carlos"))             # ¡Hola, Carlos!

Ejemplo completo: juego de dados

import random
import datetime

def tirar_dado():
    """Simula la tirada de un dado de 6 caras."""
    return random.randint(1, 6)

def jugar_ronda():
    """Una ronda del juego: dos jugadores tiran el dado."""
    jugador1 = tirar_dado()
    jugador2 = tirar_dado()
    return jugador1, jugador2

def mostrar_resultado(j1, j2):
    """Muestra quién ganó la ronda."""
    print(f"  Jugador 1: {j1}  |  Jugador 2: {j2}")
    if j1 > j2:
        print("  🏆 ¡Jugador 1 gana esta ronda!")
        return 1
    elif j2 > j1:
        print("  🏆 ¡Jugador 2 gana esta ronda!")
        return 2
    else:
        print("  🤝 ¡Empate!")
        return 0

# === JUEGO PRINCIPAL ===
print("=== 🎲 JUEGO DE DADOS ===")
print(f"Fecha: {datetime.datetime.now().strftime('%d/%m/%Y %H:%M')}\n")

puntuacion = [0, 0]  # [jugador1, jugador2]
rondas = int(input("¿Cuántas rondas quieres jugar? "))

for ronda in range(1, rondas + 1):
    print(f"\n--- Ronda {ronda} ---")
    j1, j2 = jugar_ronda()
    ganador = mostrar_resultado(j1, j2)
    if ganador == 1:
        puntuacion[0] += 1
    elif ganador == 2:
        puntuacion[1] += 1

print("\n=== RESULTADO FINAL ===")
print(f"Jugador 1: {puntuacion[0]}  |  Jugador 2: {puntuacion[1]}")
if puntuacion[0] > puntuacion[1]:
    print("🎉 ¡Jugador 1 gana la partida!")
elif puntuacion[1] > puntuacion[0]:
    print("🎉 ¡Jugador 2 gana la partida!")
else:
    print("🤝 ¡Empate final!")
💡 Consejo: Divide tu código en funciones pequeñas que hagan una sola cosa. Esto hace que el programa sea más fácil de leer, probar y mantener. Los módulos te permiten organizar y reutilizar código entre proyectos.

Resumen

  • def — Define funciones reutilizables con return para devolver valores.
  • Parámetros — Pueden tener valores por defecto; usa *args para flexible positional, **kwargs para named.
  • lambda — Funciones anónimas de una línea: lambda x: x * 2.
  • import — Trae módulos de la biblioteca estándar o propios.
  • Módulos útilesmath, random, datetime, os.
  • Tus módulos — Crea archivos .py con funciones y import desde otros scripts.

← Volver al curso