
Python Avanzado: Técnicas y Conceptos Profesionales
Domina Python avanzado con decoradores, generadores, expresiones regulares, POO avanzada y más. Tutorial completo para llevar tus habilidades al siguiente nivel.
Tutorial Avanzado de Python: Llevando tus Habilidades al Siguiente Nivel
¡Bienvenido al siguiente nivel de tu viaje con Python! Si ya dominas los fundamentos, este tutorial te llevará a explorar características avanzadas que harán tu código más elegante, eficiente y poderoso.
1. Programación Funcional en Python
¡Descubre el poder de la programación funcional! Este paradigma revolucionario trata la computación como evaluación de funciones matemáticas, evitando datos mutables y cambiando el estado. Python te ofrece herramientas increíbles para trabajar de esta manera.
Funciones como ciudadanos de primera clase
# En Python, las funciones son objetos como cualquier otro
# Pueden ser asignadas a variables, pasadas como argumentos y retornadas
def cuadrado(x):
"""Calcula el cuadrado de un número."""
return x ** 2
# Asignar función a variable
mi_funcion = cuadrado
print(mi_funcion(5)) # 25 - llama a la función a través de la variable
# Pasar función como argumento
def aplicar_funcion(func, valor):
"""Aplica una función a un valor."""
return func(valor)
resultado = aplicar_funcion(cuadrado, 4)
print(resultado) # 16 - cuadrado(4)
¡Imagina las posibilidades cuando tratas funciones como datos!
Funciones lambda (anónimas)
# Las funciones lambda son funciones pequeñas y anónimas
# Sintaxis: lambda argumentos: expresión
multiplicar = lambda x, y: x * y
print(multiplicar(3, 4)) # 12
# Útiles para operaciones simples donde no necesitamos definir una función completa
# Ejemplo común: ordenamiento personalizado
numeros = [1, 5, 2, 8, 3]
ordenados = sorted(numeros, key=lambda x: -x) # Ordena en orden descendente
print(ordenados) # [8, 5, 3, 2, 1]
¡Funciones lambda: pequeñas pero poderosas!
Map, Filter y Reduce
from functools import reduce
numeros = [1, 2, 3, 4, 5]
# Map: aplica una función a cada elemento de una secuencia
cuadrados = list(map(lambda x: x**2, numeros))
print(cuadrados) # [1, 4, 9, 16, 25]
# Equivalente a: [x**2 for x in numeros]
# Filter: filtra elementos según una condición
pares = list(filter(lambda x: x % 2 == 0, numeros))
print(pares) # [2, 4]
# Equivalente a: [x for x in numeros if x % 2 == 0]
# Reduce: aplica una función acumulativa a una secuencia
suma_total = reduce(lambda x, y: x + y, numeros)
print(suma_total) # 15
# Equivalente a: sum(numeros)
¡Estas funciones transforman cómo procesas datos en Python!
2. Decoradores
¡Los decoradores son la magia de Python! Permiten modificar o extender el comportamiento de funciones sin cambiar su código. Es como dar superpoderes a tus funciones existentes.
Decoradores básicos
def mi_decorador(func):
"""Decorador que añade comportamiento antes y después de llamar a la función."""
def wrapper():
print("Algo sucede antes de llamar a la función")
func() # Llama a la función original
print("Algo sucede después de llamar a la función")
return wrapper
@mi_decorador # Sintaxis de azúcar para: decir_hola = mi_decorador(decir_hola)
def decir_hola():
print("¡Hola!")
decir_hola()
# Salida:
# Algo sucede antes de llamar a la función
# ¡Hola!
# Algo sucede después de llamar a la función
¡Un simple @ y tu función tiene superpoderes!
Decoradores con argumentos
def repetir(n_veces):
"""Decorador que repite la ejecución de una función n_veces."""
def decorador_repetir(func):
def wrapper(*args, **kwargs):
for _ in range(n_veces):
resultado = func(*args, **kwargs) # Llama a la función original
return resultado
return wrapper
return decorador_repetir
@repetir(n_veces=3) # Primero se llama a repetir(3), luego el resultado decora saludar
def saludar(nombre):
print(f"Hola {nombre}")
saludar("Mundo")
# Salida:
# Hola Mundo
# Hola Mundo
# Hola Mundo
¡Decoradores que aceptan parámetros: el siguiente nivel de personalización!
3. Generadores
¡Descubre la eficiencia de los generadores! Son funciones especiales que permiten iterar sobre secuencias sin almacenar todo en memoria. Perfectos para datos grandes.
Generadores con yield
def generador_numeros(n):
"""Generador que produce números desde 0 hasta n-1."""
i = 0
while i < n:
yield i # Pausa la función y devuelve i
i += 1 # La función continúa desde aquí cuando se solicita el siguiente valor
# Uso del generador
for numero in generador_numeros(5):
print(numero)
# Salida: 0, 1, 2, 3, 4
# Los generadores son eficientes en memoria
# Solo producen un valor a la vez en lugar de crear una lista completa
¡Generadores: eficientes y elegantes!
Expresiones generadoras
# Similar a las list comprehension pero con paréntesis
cuadrados = (x**2 for x in range(5))
# Los generadores son iterables
for cuadrado in cuadrados:
print(cuadrado)
# Salida: 0, 1, 4, 9, 16
# Útil para grandes volúmenes de datos
# Ejemplo: procesar un archivo muy grande línea por línea sin cargarlo completo en memoria
¡Expresiones generadoras: la forma más elegante de crear generadores!
4. Manejo Avanzado de Archivos
¡Domina el arte de trabajar con archivos! Aprende a manejar formatos populares como JSON y CSV para persistir y compartir datos.
Trabajo con JSON
import json
# JSON (JavaScript Object Notation) es un formato popular para intercambio de datos
datos = {
"nombre": "Ana",
"edad": 25,
"hobbies": ["leer", "programar", "cocinar"]
}
# Escribir JSON en un archivo
with open("datos.json", "w") as archivo:
json.dump(datos, archivo, indent=4) # indent para formato legible
# Leer JSON desde un archivo
with open("datos.json", "r") as archivo:
datos_cargados = json.load(archivo)
print(datos_cargados["nombre"]) # Ana
¡JSON: el lenguaje universal de los datos!
Trabajo con CSV
import csv
# CSV (Comma-Separated Values) es un formato común para datos tabulares
# Escribir CSV
with open("datos.csv", "w", newline="") as archivo:
writer = csv.writer(archivo)
writer.writerow(["Nombre", "Edad", "Ciudad"]) # Escribir encabezados
writer.writerow(["Ana", 25, "Madrid"])
writer.writerow(["Carlos", 30, "Barcelona"])
# Leer CSV
with open("datos.csv", "r") as archivo:
reader = csv.reader(archivo)
for fila in reader:
print(fila)
# Salida:
# ['Nombre', 'Edad', 'Ciudad']
# ['Ana', '25', 'Madrid']
# ['Carlos', '30', 'Barcelona']
¡CSV: simple pero efectivo para datos tabulares!
5. Programación Orientada a Objetos Avanzada
¡Lleva la POO al siguiente nivel! Descubre métodos especiales, propiedades y técnicas avanzadas que harán tus clases más poderosas y expresivas.
Métodos especiales (Dunder Methods)
class Vector:
"""Clase que representa un vector 2D."""
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
"""Devuelve una representación legible del vector."""
return f"Vector({self.x}, {self.y})"
def __add__(self, otro):
"""Suma dos vectores."""
return Vector(self.x + otro.x, self.y + otro.y)
def __mul__(self, escalar):
"""Multiplica el vector por un escalar."""
return Vector(self.x * escalar, self.y * escalar)
v1 = Vector(2, 3)
v2 = Vector(1, 4)
v3 = v1 + v2 # Llama a v1.__add__(v2)
print(v3) # Vector(3, 7)
v4 = v3 * 2 # Llama a v3.__mul__(2)
print(v4) # Vector(6, 14)
¡Métodos dunder: operadores personalizados para tus clases!
Propiedades (@property)
class Circulo:
"""Clase que representa un círculo con validación."""
def __init__(self, radio):
self._radio = radio # Atributo "privado" (convención)
@property
def radio(self):
"""Getter para el radio."""
return self._radio
@radio.setter
def radio(self, valor):
"""Setter para el radio con validación."""
if valor <= 0:
raise ValueError("El radio debe ser positivo")
self._radio = valor
@property
def area(self):
"""Propiedad calculada: área del círculo."""
return 3.1416 * self.radio ** 2
circulo = Circulo(5)
print(circulo.area) # 78.54 - Accede como propiedad, no como método
circulo.radio = 10 # Usa el setter con validación
print(circulo.area) # 314.16
# circulo.radio = -5 # Esto lanzaría ValueError
¡Propiedades: métodos que se comportan como atributos!
6. Manejo de Fechas y Tiempos
¡Domina el tiempo con Python! El módulo datetime te da control total sobre fechas y horas.
from datetime import datetime, timedelta
# datetime es un módulo para trabajar con fechas y horas
# Fecha y hora actual
ahora = datetime.now()
print(ahora) # 2023-10-15 14:30:45.123456
# Formatear fechas
fecha_formateada = ahora.strftime("%d/%m/%Y %H:%M:%S")
print(fecha_formateada) # 15/10/2023 14:30:45
# Parsear fechas (convertir texto a datetime)
fecha = datetime.strptime("2023-12-25", "%Y-%m-%d")
print(fecha) # 2023-12-25 00:00:00
# Operaciones con fechas
mañana = ahora + timedelta(days=1) # Suma un día
diferencia = mañana - ahora # Diferencia entre fechas
print(diferencia.total_seconds()) # 86400.0 (segundos en un día)
¡Controla el tiempo como un maestro!
7. Expresiones Regulares
¡Conviértete en un maestro de los patrones! Las expresiones regulares te permiten buscar y manipular texto con precisión quirúrgica.
import re
# Las expresiones regulares permiten buscar patrones en texto
texto = "Mi teléfono es 123-456-7890 y mi otro teléfono es 987-654-3210"
# Buscar todos los números de teléfono en el formato XXX-XXX-XXXX
patron = r'\d{3}-\d{3}-\d{4}' # \d = dígito, {3} = exactamente 3 veces
telefonos = re.findall(patron, texto)
print(telefonos) # ['123-456-7890', '987-654-3210']
# Validar formato de email
def validar_email(email):
patron = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
# Explicación del patrón:
# ^ = inicio de cadena
# [a-zA-Z0-9._%+-]+ = uno o más caracteres permitidos
# @ = literalmente @
# [a-zA-Z0-9.-]+ = uno o más caracteres para el dominio
# \. = punto literal
# [a-zA-Z]{2,} = dos o más letras para la extensión
# $ = fin de cadena
return re.match(patron, email) is not None
print(validar_email("[email protected]")) # True
print(validar_email("usuario@com")) # False
¡Expresiones regulares: el superpoder para manipular texto!
8. Pruebas Unitarias con unittest
¡Aprende a escribir código confiable! Las pruebas unitarias te ayudan a detectar errores temprano y mantener la calidad de tu código.
import unittest
def sumar(a, b):
"""Función simple para probar."""
return a + b
class TestOperaciones(unittest.TestCase):
"""Clase de pruebas para las operaciones matemáticas."""
def test_sumar(self):
"""Prueba la función sumar con diferentes valores."""
self.assertEqual(sumar(2, 3), 5) # Verifica que 2+3=5
self.assertEqual(sumar(-1, 1), 0) # Verifica que -1+1=0
self.assertEqual(sumar(0, 0), 0) # Verifica que 0+0=0
def test_sumar_tipos(self):
"""Prueba que sumar lanza excepción con tipos incorrectos."""
with self.assertRaises(TypeError): # Verifica que se lanza TypeError
sumar("2", 3) # No se pueden sumar str e int
if __name__ == "__main__":
# Ejecuta todas las pruebas
unittest.main()
¡Pruebas unitarias: la garantía de calidad de tu código!
9. Proyecto Integrador: Sistema de Gestión de Tareas Mejorado
¡Es hora de aplicar todo lo aprendido! Vamos a crear un sistema de gestión de tareas avanzado que integre todas las técnicas que hemos visto.
import json
from datetime import datetime
from abc import ABC, abstractmethod
# Clase abstracta para definir la interfaz de una tarea
class Tarea(ABC):
@abstractmethod
def __str__(self):
pass
@abstractmethod
def to_dict(self):
pass
@classmethod
@abstractmethod
def from_dict(cls, data):
pass
# Implementación concreta de Tarea
class TareaConcreta(Tarea):
def __init__(self, descripcion, prioridad="media", fecha_limite=None):
self.descripcion = descripcion
self.prioridad = prioridad
self.completada = False
self.fecha_creacion = datetime.now()
self.fecha_limite = fecha_limite
def __str__(self):
estado = "✓" if self.completada else "✗"
return f"[{estado}] {self.descripcion} (Prioridad: {self.prioridad})"
def to_dict(self):
"""Convierte la tarea a diccionario para serialización."""
return {
"descripcion": self.descripcion,
"prioridad": self.prioridad,
"completada": self.completada,
"fecha_creacion": self.fecha_creacion.isoformat(),
"fecha_limite": self.fecha_limite.isoformat() if self.fecha_limite else None
}
@classmethod
def from_dict(cls, data):
"""Crea una tarea desde un diccionario."""
tarea = cls(data["descripcion"], data["prioridad"])
tarea.completada = data["completada"]
tarea.fecha_creacion = datetime.fromisoformat(data["fecha_creacion"])
if data["fecha_limite"]:
tarea.fecha_limite = datetime.fromisoformat(data["fecha_limite"])
return tarea
class GestorTareasAvanzado:
def __init__(self, archivo="tareas.json"):
self.archivo = archivo
self.tareas = self.cargar_tareas()
def agregar_tarea(self, descripcion, **kwargs):
"""Añade una nueva tarea."""
tarea = TareaConcreta(descripcion, **kwargs)
self.tareas.append(tarea)
self.guardar_tareas()
def completar_tarea(self, indice):
"""Marca una tarea como completada."""
if 0 <= indice < len(self.tareas):
self.tareas[indice].completada = True
self.guardar_tareas()
def filtrar_tareas(self, criterio):
"""Filtra tareas según una función criterio."""
return list(filter(criterio, self.tareas))
def guardar_tareas(self):
"""Guarda las tareas en un archivo JSON."""
with open(self.archivo, "w") as f:
json.dump([tarea.to_dict() for tarea in self.tareas], f, indent=4)
def cargar_tareas(self):
"""Carga las tareas desde un archivo JSON."""
try:
with open(self.archivo, "r") as f:
datos = json.load(f)
return [TareaConcreta.from_dict(tarea_data) for tarea_data in datos]
except FileNotFoundError:
return []
def mostrar_tareas(self, tareas=None):
"""Muestra las tareas en la consola."""
tareas = tareas or self.tareas
for i, tarea in enumerate(tareas):
print(f"{i}. {tarea}")
# Ejemplo de uso
if __name__ == "__main__":
gestor = GestorTareasAvanzado()
# Agregar algunas tareas
gestor.agregar_tarea("Aprender Python", prioridad="alta")
gestor.agregar_tarea("Hacer ejercicio", prioridad="baja")
# Filtrar tareas no completadas
tareas_pendientes = gestor.filtrar_tareas(lambda t: not t.completada)
print("Tareas pendientes:")
gestor.mostrar_tareas(tareas_pendientes)
# Completar primera tarea
gestor.completar_tarea(0)
print("\nTodas las tareas:")
gestor.mostrar_tareas()
¡Este proyecto avanzado combina clases abstractas, serialización JSON, manejo de fechas y filtrado funcional!
10. Recursos para Continuar
¡Tu viaje apenas comienza! Para seguir avanzando en Python, aquí tienes recursos increíbles:
-
Libros avanzados:
- "Fluent Python" de Luciano Ramalho - Cubre características avanzadas de Python
- "Python Tricks" de Dan Bader - Tips y técnicas avanzadas
-
Cursos especializados:
- "Python Data Structures" en Coursera - Estructuras de datos avanzadas
- "Advanced Python" en Real Python - Tutoriales avanzados
-
Frameworks y librerías:
- Django/Flask para desarrollo web
- Pandas/NumPy para análisis de datos
- TensorFlow/PyTorch para machine learning
-
Comunidades:
- Python Discord - Comunidad activa para hacer preguntas
- Reddit r/learnpython - Para discusiones y preguntas
- Stack Overflow - Para problemas específicos de programación
¡Has llegado lejos! Este tutorial avanzado te ha equipado con herramientas poderosas. Sigue explorando, experimentando y creando. ¡El mundo del código te espera!
No hay comentarios aún
Sé el primero en comentar este tutorial.