Versión estable de Python 3.9.0

Se espera que la versión estable de Python 3.9.0 se lance hoy , 05.10.2020. La nueva versión recibirá actualizaciones de parches aproximadamente cada 2 meses durante aproximadamente 18 meses. Algún tiempo después del lanzamiento de la versión final 3.10.0, se lanzará la novena y última actualización con correcciones de errores 3.9.



“Esta es la primera versión de Python que tiene el instalador predeterminado de 64 bits en Windows. El instalador ahora también prohíbe activamente la instalación en Windows 7. "

“Esta es la primera versión de Python que utiliza el instalador de 64 bits en Windows de forma predeterminada. El instalador ahora también evita la instalación en Windows 7. "



He leído las notas de la versión de Python 3.9 y las discusiones relacionadas. Basándome en la información, quería escribir una guía completa para que todos puedan tener una idea de las funciones junto con su trabajo detallado.



UPD :

transición a ciclos de lanzamiento anuales estables, consulte PEP 602

alec_kalinin

“Cada nueva versión de Python saldrá ahora en octubre. Python 3.10 se lanzará en octubre de 2021, Python 3.11 en octubre de 2022. Buckfix se lanzará cada dos meses. Esta es una gran noticia para mí, ahora claramente podemos planear actualizar el entorno de Python ".



PEP 584



Este PEP sugiere agregar los operadores de combinación ( | ) y actualización ( | = ) a la clase dict incorporada.



Para fusionar: |



>>> a = {'milk': 'prostokvashino', 'heese': 'cheddar'} 
>>> b = {'milk': 1, 'heese': 2, 'bread': 3} 
>> >  | b 
{'milk': 1, 'heese': 2, 'bread': 3}
>>> b | a 
{'milk': 'prostokvashino', 'heese': 'cheddar', 'bread': 3}


Para actualizar: | =



>>> a | = b 
>>> a 
{'milk': 1, 'heese': 2, 'bread': 3}


La regla clave a recordar es que si hay algún conflicto de claves, se conservará el valor más a la derecha.



Por supuesto, muchos pitonistas tendrán una pregunta, ¿por qué es esto necesario, si ya existe una opción familiar para todos?



{**d1, **d2}


Esta pregunta fue respondida en el propio PEP:



Desembalar diccionarios se ve feo y no es fácil de detectar. Pocos podrán adivinar qué significa esto cuando lo vean por primera vez.


Como dijo Guido :

Pido disculpas por PEP 448 , pero incluso si conoces ** d en un contexto más simple, si le preguntaras a un usuario típico de Python cómo combinar dos dict en uno nuevo, dudo que mucha gente piense en {** d1, ** d2}. ¡Sé que lo olvidé yo mismo cuando comenzó este hilo!


Además, {** d1, ** d2} no funciona para subclases dict como defaultdict




PEP 585



Sugerencias de tipo genérico en colecciones estándar.



Genérico es un tipo que se puede parametrizar, una especie de contenedor. También conocido como tipo paramétrico o tipo genérico.



Esta versión incluye soporte de sintaxis universal para todas las colecciones estándar disponibles actualmente en el módulo de mecanografía. Podemos usar tipos list o dict como tipos genéricos en lugar de usar typing.List o typing.Dict .



Era:



from typing import List

a: List[str] = list()

def read_files(files: List[str]) -> None:
    pass


Convirtió:



a: list[str] = list()

def read_files(files: list[str]) -> None:
    pass


Lista completa de tipos
tuple

list

dict

set

frozenset

type

collections.deque

collections.defaultdict

collections.OrderedDict

collections.Counter

collections.ChainMap

collections.abc.Awaitable

collections.abc.Coroutine

collections.abc.AsyncIterable

collections.abc.AsyncIterator

collections.abc.AsyncGenerator

collections.abc.Iterable

collections.abc.Iterator

collections.abc.Generator

collections.abc.Reversible

collections.abc.Container

collections.abc.Collection

collections.abc.Callable

collections.abc.Set # typing.AbstractSet

collections.abc.MutableSet

collections.abc.Mapping

collections.abc.MutableMapping

collections.abc.Sequence

collections.abc.MutableSequence

collections.abc.ByteString

collections.abc.MappingView

collections.abc.KeysView

collections.abc.ItemsView

collections.abc.ValuesView

contextlib.AbstractContextManager # typing.ContextManager

contextlib.AbstractAsyncContextManager # typing.AsyncContextManager

re.Pattern # typing.Pattern, typing.re.Pattern

re.Match # typing.Match, typing.re.Match



PEP 615



Soporte de base de datos de zona horaria de IANA en la biblioteca estándar.



Las zonas horarias de IANA a menudo se denominan tz o información de zona. Hay una gran cantidad de zonas horarias de IANA con diferentes rutas de búsqueda para especificar la zona horaria de IANA para un objeto de fecha y hora. Por ejemplo, podemos pasar el nombre de la ruta de búsqueda como Continente / Ciudad a un objeto de fecha y hora para establecer su tzinfo.



dt: datetime = datetime(2000, 01, 25, 01, tzinfo=ZoneInfo("Europe/London"))


Si pasamos la clave incorrecta, se lanzará una excepción

zoneinfo.ZoneInfoNotFoundError

PEP 616



Nuevas funciones de cadena para eliminar prefijo y sufijo. Se han agregado dos funciones nuevas



al objeto str .



  • La primera función elimina el prefijo.
    str.removeprefix(prefix)
  • La segunda función elimina el sufijo.
    str.removesuffix(suffix)


>>> 'hello_world'.removeprefix ('hello_') 
world
>>> 'hello_world'.removesuffix ('_world') 
hello


PEP 617



Python 3.9 propone reemplazar el actual analizador de Python basado en LL (1) con un nuevo analizador basado en PEG que es estable y de alto rendimiento.



El analizador actual de CPython está basado en LL (1). Posteriormente, la gramática se basa en LL (1), lo que permite analizarla con un analizador LL (1). El analizador LL (1) funciona de arriba a abajo. Además, analiza los datos de entrada de izquierda a derecha. La gramática actual es gramática libre de contexto, por lo que el contexto de los tokens no se tiene en cuenta.

Python 3.9 propone reemplazarlo con un nuevo analizador basado en PEG, lo que significa que eliminará las limitaciones actuales de la gramática LL de Python (1). Además, se han realizado correcciones en el analizador actual, agregando una serie de hacks que se eliminarán. Como resultado, esto reducirá el costo de mantenimiento a largo plazo.



Por ejemplo, aunque los analizadores sintácticos y las gramáticas LL (1) son fáciles de implementar, las restricciones les impiden expresar construcciones comunes de forma natural para el diseñador y el lector del lenguaje. El analizador solo mira un token hacia adelante para distinguir entre posibilidades.



número30966



Posibilidad de cancelar futuros simultáneos .



Se ha agregado un nuevo parámetro cancel_futures a concurrent.futures.Executor.shutdown () .



Este parámetro contiene todos los futuros pendientes que aún no han comenzado. Antes de la versión 3.9, el proceso esperaba a que se completaran antes de que el ejecutor saliera. Se ha agregado un



nuevo parámetro cancel_futures a ThreadPoolExecutor y ProcessPoolExecutor . Funciona cuando el valor del parámetro es Verdadero, entonces todos los futuros pendientes se cancelarán cuando se llame a la función shutdown () .



Cuando se apaga ()se ejecuta, el intérprete verifica si el ejecutor es basura recolectada. Si todavía está en la memoria, obtiene los elementos pendientes y luego cancela los futuros.



número30966



Se han realizado una serie de mejoras en la biblioteca de multiprocesamiento y asyncio en esta versión.



Por ejemplo,



  1. El parámetro reuse_address asyncio.loop.create_datagram_endpoint () ya no es compatible debido a problemas de seguridad importantes.
  2. Se agregaron nuevas corrutinas, shutdown_default_executor () y asyncio.to_thread () . Se usa una nueva llamada a asyncio.to_thread () para ejecutar funciones relacionadas con E / S en un hilo separado para evitar bloquear el bucle de eventos.


En cuanto a las mejoras a la biblioteca de multiprocesamiento, se ha agregado un nuevo método close () a la clase multiprocessing.SimpleQueue . Este método cierra explícitamente la cola. Esto asegura que la cola esté cerrada y no se quede más de lo esperado. Es importante recordar que los métodos get (), put (), empty () no se pueden llamar después de cerrar la cola.







número37444



Error solucionado con la importación de paquetes.



El principal problema con la importación de bibliotecas de Python antes de la versión 3.9 era el comportamiento de importación inconsistente en Python cuando las importaciones relativas pasaban por su paquete de nivel superior.



builtins .__ import __ () generó ValueError mientras que importlib .__ import __ () generó ImportError.



Ahora está corregido . __Import __ () ahora genera ImportError en lugar de ValueError.



número40286



Generación de bytes aleatorios.



Otra característica que se agregó en la versión 3.9 es random.Random.randbytes () . Se puede utilizar para generar bytes aleatorios.



Podemos generar números aleatorios, pero ¿y si necesitáramos generar bytes aleatorios? Antes de la versión 3.9, los desarrolladores tenían que ser creativos para generar bytes aleatorios. Aunque podemos usar os.getrandom () , os.urandom () o secrets.token_bytes (), no podemos generar patrones pseudoaleatorios.



Por ejemplo, para garantizar que los números aleatorios se generen con el comportamiento esperado y el proceso se reproduzca, usualmente usamos semilla con el módulo random.Random.



Como resultado, se introdujo el método random.Random.randbytes () . Genera bytes aleatorios.



número28029



Corrección de la función de sustitución de cuerdas.



El principio de la función de reemplazo es que para que un argumento máximo dado reemplace una ocurrencia, reemplaza el juego de caracteres de la cadena con el nuevo juego de caracteres.



Para explicar mejor el problema, antes de la versión 3.9, la función de reemplazo tenía un comportamiento inconsistente:



uno esperaría ver un blog



"" .replace ("", "blog", 1) 
>>> '' 




Uno esperaría ver |



"" .replace ("", "|", 1) 
>>> '' 




"" .replace ("", "prefix") 
>>> 'prefix'




número39648, número39479, número39288, número39310



Cambios en el módulo "matemáticas".



Devuelve el mínimo común múltiplo de argumentos enteros:



>>> import  math 
>>> math.lcm(48,72,108) 
432




Devuelve el máximo común divisor de argumentos enteros. En la versión anterior, solo se admitían dos argumentos. Se agregó soporte para una cantidad arbitraria de argumentos:



>>> import  math 
>>> math.gcd(9,12,21) 
3




Calcula el número de punto flotante más cercano a " x " en la dirección de " y ".



>>> math.nextafter(2, -1)
1.9999999999999998




Este método devuelve el valor del bit menos significativo del número de coma flotante x.



>>> 1 - math.ulp(1)
0.9999999999999998
>>> math.nextafter(1, -1) + math.ulp(1)
1.0




número38870



El método unparse se agregó al módulo ast.

El nuevo método se puede utilizar para crear una línea de código y luego ejecutarlo.



>>> import ast
>>> parsed = ast.parse('from sys import platform; print(platform)')
>>> unparsed_str = ast.unparse(parsed)
>>> print(unparsed_str)
from sys import platform
print(platform)
>>> exec(unparsed_str)
win32




número39507, número39509



Añadiendo nuevos códigos a http.HTTPStatus.



Ahorre 418! "

418 IM_A_TEAPOT
103 EARLY_HINTS
425 TOO_EARLY




UPD :

PEP 614



Relajantes restricciones gramaticales para decoradores.



Era:



buttons = [QPushButton(f'Button {i}') for i in range(10)]

button_0 = buttons[0]

@button_0.clicked.connect
def spam():
    ...

button_1 = buttons[1]

@button_1.clicked.connect
def eggs():
    ...


Ahora puede eliminar asignaciones innecesarias y llamar directamente:



buttons = [QPushButton(f'Button {i}') for i in range(10)]

@buttons[0].clicked.connect
def spam():
    ...

@buttons[1].clicked.connect
def eggs():
    ...




"La tupla debe estar entre paréntesis".



Esto se basa en la visión de Guido en la misma carta. Citar:



Pero no permitiré las comas. No puedo estar de acuerdo con esto



@f, g
def pooh(): ...


Esto puede llevar a los programadores sin experiencia a la conclusión de que de esta manera se pueden llamar a varios decoradores seguidos. Los paréntesis son necesarios para aclarar todo sin restricciones adicionales o sintaxis compleja.




número17005



El nuevo módulo graphlib proporciona funcionalidad para la clasificación topológica de un gráfico de nodos hash.

Se pueden encontrar más detalles en la documentación .



UPD :ifinik

imagen



>>> from graphlib import TopologicalSorter 
>>> graph = {'E': {'C', 'F'}, 'D': {'B', 'C'}, 'B': {'A'}, 'A': {'F'}} 
>>> ts = TopologicalSorter(graph) 
>>> tuple(ts.static_order()) 
('C', 'F', 'E', 'A', 'B', 'D')
>>> tuple(ts.static_order())
('F', 'C', 'A', 'E', 'B', 'D')


El gráfico no se puede transferir inmediatamente, sino completar el TopologicalSorter utilizando el método de adición . Además, la clase está adaptada a la computación en paralelo y se puede utilizar, por ejemplo, para crear una cola de tareas.



número37630, número40479



Actualización de la biblioteca hashlib.

Hashlib ahora puede usar hash SHA3 y SHAKE XOF de OpenSSL.

Los módulos hash incorporados ahora se pueden desactivar o activar de forma selectiva, por ejemplo, para forzar una implementación basada en OpenSSL.



Mejoramiento



Un resumen de las mejoras de rendimiento de Python 3.4 a Python 3.9:



Python version                       3.4     3.5     3.6     3.7     3.8    3.9
--------------                       ---     ---     ---     ---     ---    ---

Variable and attribute read access:
    read_local                       7.1     7.1     5.4     5.1     3.9    4.0
    read_nonlocal                    7.1     8.1     5.8     5.4     4.4    4.8
    read_global                     15.5    19.0    14.3    13.6     7.6    7.7
    read_builtin                    21.1    21.6    18.5    19.0     7.5    7.7
    read_classvar_from_class        25.6    26.5    20.7    19.5    18.4   18.6
    read_classvar_from_instance     22.8    23.5    18.8    17.1    16.4   20.1
    read_instancevar                32.4    33.1    28.0    26.3    25.4   27.7
    read_instancevar_slots          27.8    31.3    20.8    20.8    20.2   24.5
    read_namedtuple                 73.8    57.5    45.0    46.8    18.4   23.2
    read_boundmethod                37.6    37.9    29.6    26.9    27.7   45.9

Variable and attribute write access:
    write_local                      8.7     9.3     5.5     5.3     4.3    4.2
    write_nonlocal                  10.5    11.1     5.6     5.5     4.7    4.9
    write_global                    19.7    21.2    18.0    18.0    15.8   17.2
    write_classvar                  92.9    96.0   104.6   102.1    39.2   43.2
    write_instancevar               44.6    45.8    40.0    38.9    35.5   40.7
    write_instancevar_slots         35.6    36.1    27.3    26.6    25.7   27.7

Data structure read access:
    read_list                       24.2    24.5    20.8    20.8    19.0   21.1
    read_deque                      24.7    25.5    20.2    20.6    19.8   21.6
    read_dict                       24.3    25.7    22.3    23.0    21.0   22.5
    read_strdict                    22.6    24.3    19.5    21.2    18.9   21.6

Data structure write access:
    write_list                      27.1    28.5    22.5    21.6    20.0   21.6
    write_deque                     28.7    30.1    22.7    21.8    23.5   23.2
    write_dict                      31.4    33.3    29.3    29.2    24.7   27.8
    write_strdict                   28.4    29.9    27.5    25.2    23.1   29.8

Stack (or queue) operations:
    list_append_pop                 93.4   112.7    75.4    74.2    50.8   53.9
    deque_append_pop                43.5    57.0    49.4    49.2    42.5   45.5
    deque_append_popleft            43.7    57.3    49.7    49.7    42.8   45.5

Timing loop:
    loop_overhead                    0.5     0.6     0.4     0.3     0.3    0.3


El script de prueba muestra el tiempo en nanosegundos. Las pruebas se realizaron en un procesador Intel Core i7-4960HQ . El código de prueba se puede encontrar en el repositorio en " Tools / scripts / var_access_benchmark.py " .



Gracias por su atención.



Enlace al manual oficial de Python 3.9.

Anula la suscripción en los comentarios si te perdiste algo.



All Articles