Python lanza versiones menores cada año. Python 3.12 (octubre 2023) y Python 3.13 (octubre 2024) introdujeron mejoras relevantes para el día a día: f-strings sin restricciones, alias de tipo con sintaxis propia, el decorador @override y generics sin TypeVar. Python 3.13 suma un REPL renovado, un JIT experimental y los primeros pasos hacia la eliminación opcional del GIL.
Python 3.12: f-strings sin restricciones
Hasta 3.11, las f-strings no podían contener backslashes ni comillas del mismo tipo que las exteriores dentro de las expresiones {}. Python 3.12 elimina esas limitaciones.
# Python 3.11: esto daba SyntaxError
# f"resultado: {'n'.join(nombres)}" # backslash no permitido dentro de {}
# Python 3.12: funciona sin problemas
nombres = ["Ana", "Luis", "Marta"]
print(f"Lista:n{'n'.join(nombres)}")
# Comillas anidadas del mismo tipo
datos = {"clave": "valor"}
print(f"Valor: {datos["clave"]}") # antes necesitabas cambiar las comillas externas
# Expresiones multi-línea dentro de f-strings
resultado = f"""
Suma: {
sum(range(10))
}
"""
print(resultado.strip()) # Suma: 45
# Ahora puedes usar dict comprehensions dentro de f-strings
valores = [1, 2, 3, 4, 5]
print(f"Cuadrados: { {v: v**2 for v in valores} }")
Python 3.12: type alias con la sentencia type
# Antes de 3.12
from typing import TypeAlias
Vector: TypeAlias = list[float]
Matriz: TypeAlias = list[list[float]]
# Python 3.12+: sintaxis nativa
type Vector = list[float]
type Matriz = list[list[float]]
type Callback[T] = Callable[[T], None] # alias genérico
def normalizar(v: Vector) -> Vector:
modulo = sum(x**2 for x in v) ** 0.5
return [x / modulo for x in v]
print(normalizar([3.0, 4.0])) # [0.6, 0.8]
Python 3.12: generics sin TypeVar
# Antes de 3.12
from typing import TypeVar, Generic
T = TypeVar("T")
class Pila(Generic[T]):
def __init__(self) -> None:
self._items: list[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
# Python 3.12+: sintaxis con [T] directamente
class Pila[T]:
def __init__(self) -> None:
self._items: list[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
def primero[T](seq: list[T]) -> T:
return seq[0]
pila: Pila[int] = Pila()
pila.push(42)
print(pila.pop()) # 42
Python 3.12: @override para herencia segura
from typing import override
class Animal:
def hablar(self) -> str:
return "..."
def moverse(self) -> str:
return "andando"
class Perro(Animal):
@override
def hablar(self) -> str: # mypy/pyright verifican que esta firma existe en el padre
return "Guau"
@override
def moverse(self) -> str:
return "corriendo"
# Si renombras 'hablar' a 'hacer_ruido' en Animal sin actualizar Perro,
# @override provoca un error en el análisis estático
Python 3.13: REPL mejorado
El REPL de Python 3.13 incorpora edición multilínea, historial persistente, resaltado de sintaxis y autocompletado mejorado sin necesidad de ipython ni bpython.
# Nuevas opciones al lanzar el intérprete:
# python -c "import sys; print(sys.version)" ? 3.13.x
# Dentro del REPL:
# - Edición de bloques multilínea con flechas
# - Ctrl+F para búsqueda en historial
# - Coloreado de errores (tracebacks en color por defecto)
# - help() integrado con paginación
# Ejemplo: puedes escribir y editar una función completa
def saludar(nombre):
return f"Hola, {nombre}"
Python 3.13: JIT experimental y free-threaded mode
# JIT (compilador just-in-time) activar en tiempo de compilación de CPython
# Compilar Python con --enable-experimental-jit
# Mejora de rendimiento: 5-15% en benchmarks típicos (varía mucho por workload)
# Free-threaded CPython (PEP 703): sin GIL
# Compilar con --disable-gil (Python 3.13t)
# Permite que múltiples threads corran en paralelo real en CPU-bound
# Estado: experimental, algunas extensiones C no son compatibles todavía
import sys
print(sys._is_gil_enabled()) # True (normal) o False (free-threaded build)
# En Python 3.13t (free-threaded):
import threading
resultados = []
def calcular(n):
resultados.append(sum(range(n)))
threads = [threading.Thread(target=calcular, args=(1_000_000,)) for _ in range(4)]
for t in threads: t.start()
for t in threads: t.join()
print(len(resultados)) # 4 paralelo real en free-threaded
Resumen de novedades por versión
- 3.12: f-strings sin límites,
typealias, generics con[T],@override, mejor rendimiento del intérprete (+5%). - 3.13: REPL reescrito, JIT experimental, free-threaded CPython (sin GIL opcional),
locals()con semántica mejorada, deprecaciones limpiadas. - Migración:
python -W error::DeprecationWarning mi_script.pypara detectar código que dejará de funcionar.
# Comprobar la versión en tiempo de ejecución
import sys
if sys.version_info >= (3, 12):
type Vector = list[float] # sintaxis 3.12+
else:
from typing import TypeAlias
Vector: TypeAlias = list[float]
print(f"Python {sys.version_info.major}.{sys.version_info.minor}")
La recomendación práctica: si empiezas un proyecto nuevo, usa Python 3.12 como mínimo para aprovechar los generics simplificados y las f-strings sin restricciones. Si tu entorno de producción todavía no soporta 3.12, from __future__ import annotations aplaza la evaluación de type hints y te da compatibilidad hacia atrás.
