Módulo 3: Python Avanzado
Decoradores
Los decoradores son una de las características más elegantes y potentes de Python. Permiten modificar o extender el comportamiento de funciones o clases sin alterar su código fuente.
Fundamentos de los Decoradores
Un decorador es esencialmente una función que toma otra función como argumento, le añade alguna funcionalidad y la devuelve.
def mi_decorador(func):
def wrapper(*args, **kwargs):
print("Antes de llamar a la función.")
resultado = func(*args, **kwargs)
print("Después de llamar a la función.")
return resultado
return wrapper
@mi_decorador
def saludar(nombre):
print(f"Hola, {nombre}!")
saludar("Alice")
# Salida:
# Antes de llamar a la función.
# Hola, Alice!
# Después de llamar a la función.
Decoradores con Argumentos
Los decoradores pueden aceptar argumentos adicionales, lo que añade flexibilidad.
def repetir(veces):
def decorador(func):
def wrapper(*args, **kwargs):
for _ in range(veces):
func(*args, **kwargs)
return wrapper
return decorador
@repetir(veces=3)
def mensaje():
print("Este mensaje se repite.")
mensaje()
# Salida:
# Este mensaje se repite.
# Este mensaje se repite.
# Este mensaje se repite.
Generadores e Iteradores
Los generadores son funciones que pueden pausar y reanudar su ejecución, produciendo una secuencia de valores lazy (uno a la vez, bajo demanda). Son muy eficientes en memoria para trabajar con grandes conjuntos de datos.
Funciones Generadoras (yield)
def contador_infinito():
n = 0
while True:
yield n
n += 1
gen = contador_infinito()
print(next(gen)) # 0
print(next(gen)) # 1
Expresiones Generadoras
Son similares a las comprensiones de listas, pero usan paréntesis () y crean un objeto generador.
cuadrados_lazy = (x*x for x in range(1000000))
# Solo se calcula un cuadrado a la vez cuando se itera
Programación Asíncrona (asyncio)
Python ofrece un soporte robusto para la programación asíncrona, lo que permite realizar múltiples operaciones (especialmente E/S) de manera concurrente sin usar múltiples hilos de CPU.
async y await
async def: Define una función como una coroutine (corutina).await: Pausa la ejecución de la coroutine hasta que otra coroutine termine.
import asyncio
async def tarea(nombre, duracion):
print(f"Tarea {nombre}: comenzando...")
await asyncio.sleep(duracion) # Pausa la coroutine, no el programa entero
print(f"Tarea {nombre}: terminada después de {duracion} segundos.")
async def main():
await asyncio.gather(
tarea("A", 2),
tarea("B", 1)
)
if __name__ == "__main__":
asyncio.run(main())
# Salida (aproximada, B termina antes):
# Tarea A: comenzando...
# Tarea B: comenzando...
# Tarea B: terminada después de 1 segundos.
# Tarea A: terminada después de 2 segundos.
Metaprogramación
La metaprogramación es la capacidad de un programa para tratarse a sí mismo o a otros programas como datos. En Python, esto a menudo implica el uso de type, exec, eval y metaclasses.
Metaclasses
Las metaclasses son las “fábricas” de clases. Permiten controlar cómo se crean las clases.
class MetaMiClase(type):
def __new__(mcs, name, bases, attrs):
# Aquí puedes modificar la clase antes de que se cree
attrs['version'] = '1.0'
return super().__new__(mcs, name, bases, attrs)
class MiClase(metaclass=MetaMiClase):
pass
print(MiClase.version) # 1.0
Conclusión
Este módulo ha explorado algunas de las características más avanzadas y poderosas de Python, como los decoradores, generadores, la programación asíncrona y la metaprogramación. Dominar estos conceptos te permitirá escribir código más conciso, eficiente y flexible, abriendo las puertas a la construcción de sistemas complejos y de alto rendimiento.