Después de un año de desarrollo, se ha publicado una importante versión del lenguaje de programación Python 3.11. Esta nueva rama se mantendrá durante un año y medio, tras lo cual se proporcionarán correcciones de vulnerabilidades durante otros tres años y medio.
Simultáneamente, ha comenzado la fase de pruebas alfa de la rama Python 3.12 (de acuerdo con el nuevo calendario de desarrollo, el trabajo en la nueva rama comienza cinco meses antes del lanzamiento de la rama anterior, alcanzando la etapa de pruebas alfa en el momento del próximo lanzamiento). La rama Python 3.12 estará en fase de lanzamientos alfa durante siete meses, durante los cuales se añadirán nuevas características y se corregirán errores. Después, durante tres meses, se realizarán pruebas de las versiones beta, en las que no se permitirá la incorporación de nuevas características y toda la atención se centrará en la corrección de errores. Los últimos dos meses antes del lanzamiento, la rama estará en la fase de candidato a lanzamiento, donde se realizará la estabilización final.
Entre las novedades añadidas en Python 3.11:
- Se ha realizado un trabajo significativo en la optimización del rendimiento. La nueva rama incluye cambios relacionados con la aceleración y la expansión en línea de las llamadas a funciones, la aplicación de intérpretes rápidos para operaciones típicas (x+x, x*x, x-x, a[i], a[i] = z, f(arg), C(arg), o.method(), o.attr = z, *seq), así como optimizaciones desarrolladas por los proyectos Cinder y HotPy. Dependiendo del tipo de carga, se observa un aumento en la velocidad de ejecución del código del 10 al 60%. En promedio, el rendimiento al pasar por el conjunto de pruebas pyperformance ha aumentado un 25%.
Se ha rediseñado el mecanismo de almacenamiento en caché del bytecode, lo que ha permitido reducir el tiempo de inicio del intérprete en un 10-15%. Los objetos con código y bytecode ahora son colocados estáticamente por el intérprete, lo que ha permitido eliminar las etapas de desmarshalling del bytecode extraído de la caché y la conversión de objetos con código para su ubicación en la memoria dinámica.
- Al mostrar el seguimiento de llamadas en los mensajes de diagnóstico, se ha asegurado la salida de información sobre la expresión que causó el error (anteriormente solo se resaltaba la línea sin detallar qué parte de la línea fue la causante del error). También se puede obtener información ampliada sobre el seguimiento a través de la API y utilizarla para mapear instrucciones individuales de bytecode a una posición específica en el código fuente, utilizando el método codeobject.co_positions() o la función C API PyCode_Addr2Location(). Este cambio simplifica enormemente la depuración de problemas relacionados con objetos de diccionarios anidados, múltiples llamadas a funciones y expresiones aritméticas complejas. Traceback (most recent call last): File «calculation.py», line 54, in result = (x / y / z) * (a / b / c) ~~~~~~^~~ ZeroDivisionError: division by zero
- Se ha añadido soporte para grupos de excepciones, lo que permite a la aplicación generar y manejar múltiples excepciones diferentes simultáneamente. Para agrupar varias excepciones y llamarlas juntas, se han introducido nuevos tipos de excepciones ExceptionGroup y BaseExceptionGroup, y para extraer excepciones individuales de un grupo se ha añadido la expresión «except*».
- En la clase BaseException se ha añadido el método add_note(), que permite adjuntar un texto de nota a la excepción, por ejemplo, añadir información de contexto que no está disponible durante la generación de la excepción.
- Se ha añadido un tipo especial Self, que representa la clase cerrada actual. Self puede usarse para anotar métodos que devuelven una instancia de su propia clase de manera más simple que al usar TypeVar. class MyLock: def __enter__(self) -> Self: self.lock() return self
- Se ha añadido un nuevo tipo LiteralString, que puede incluir solo literales de cadena compatibles con el tipo LiteralString (es decir, cadenas simples y cadenas del tipo LiteralString, pero no cadenas arbitrarias o combinadas del tipo str). El tipo LiteralString se puede usar para restringir el paso de argumentos de cadena a funciones, ya que la sustitución arbitraria de partes de cadena puede conducir a vulnerabilidades, como al formar cadenas para consultas SQL o comandos de shell. def run_query(sql: LiteralString) -> … … def caller( arbitrary_string: str, query_string: LiteralString, table_name: LiteralString, ) -> None: run_query(«SELECT * FROM students») # ok run_query(literal_string) # ok run_query(«SELECT * FROM » + literal_string) # ok run_query(arbitrary_string) # Error run_query( # Error f»SELECT * FROM students WHERE name = {arbitrary_string}» )
- Se ha añadido el tipo TypeVarTuple, que permite utilizar genéricos variádicos, a diferencia de TypeVar, que abarca un número arbitrario de tipos.
- Se ha incorporado a la biblioteca estándar el módulo tomllib con funciones para analizar el formato TOML.
- Se ha proporcionado la capacidad de marcar elementos individuales de diccionarios tipados (TypedDict) con las etiquetas Required y NotRequired para definir campos obligatorios y no obligatorios (por defecto, todos los campos declarados son obligatorios si el parámetro total no se establece en False). class Movie(TypedDict): title: str year: NotRequired[int] m1: Movie = {«title»: «Black Panther», «year»: 2018} # OK m2: Movie = {«title»: «Star Wars»} # OK (el campo year es opcional) m3: Movie = {«year»: 2022} # Error, no se rellenó el campo obligatorio title)
- Se ha añadido a la módulo asyncio la clase TaskGroup con la implementación de un gestor de contexto asincrónico, que espera la finalización de un grupo de tareas. La adición de tareas al grupo se realiza mediante el método create_task(). async def main(): async with asyncio.TaskGroup() as tg: task1 = tg.create_task(some_coro(…)) task2 = tg.create_task(another_coro(…)) print(«Ambas tareas se han completado ahora.»)
- Se ha añadido el decorador para clases, métodos y funciones @dataclass_transform, al indicar el cual el sistema de verificación de tipos estáticos interpreta el objeto como si se estuviera utilizando el decorador @dataclasses.dataclass. En el ejemplo a continuación, la clase CustomerModel será procesada durante la verificación de tipos de manera similar a una clase con el decorador @dataclasses.dataclass, es decir, como si tuviera un método __init__ que acepta las variables id y name. @dataclass_transform() class ModelBase: … class CustomerModel(ModelBase): id: int name: str
- Se ha añadido la posibilidad de usar agrupación atómica ((?>…)) y cuantificadores celosos (possessive) (*+, ++, ?+, {m,n}+).
- Se ha añadido la opción de línea de comandos «-P» y la variable de entorno PYTHONSAFEPATH para desactivar la vinculación automática de rutas de archivos potencialmente inseguras a sys.path.
- Se ha mejorado significativamente la utilidad py.exe para la plataforma Windows, que ahora incluye soporte para la sintaxis «-V:<empresa>/<etiqueta>» además de «-<mayor>.<menor>».
- Muchos macros en la API de C se han convertido en funciones inline regulares o estáticas.
- Se han declarado obsoletos y se eliminarán en la versión Python 3.13 los módulos uu, cgi, pipes, crypt, aifc, chunk, msilib, telnetlib, audioop, nis, sndhdr, imghdr, nntplib, spwd, xdrlib, cgitb, mailcap, ossaudiodev y sunau. Se han eliminado las funciones PyUnicode_Encode*.
Fuente: opennet.ru
