Version stable de Python 3.9.0

La version stable de Python 3.9.0 devrait être publiée aujourd'hui , 10/05/2020. La nouvelle version recevra des mises à jour corrigées environ tous les 2 mois pendant environ 18 mois. Quelque temps après la sortie de la version finale 3.10.0, la neuvième et dernière mise à jour sera publiée avec des corrections de bogues 3.9.



«Il s'agit de la première version de Python à utiliser par défaut le programme d'installation 64 bits sous Windows. Le programme d’installation interdit désormais activement l’installation sous Windows 7. »

«Il s'agit de la première version de Python à utiliser le programme d'installation 64 bits sur Windows par défaut. Le programme d'installation empêche désormais également l'installation sur Windows 7. "



J'ai lu les notes de publication de Python 3.9 et les discussions connexes. Sur la base des informations, j'ai voulu rédiger un guide complet afin que chacun puisse se faire une idée des fonctions ainsi que de leur travail détaillé.



UPD :

transition vers des cycles de publication annuels stables, voir PEP 602

alec_kalinin

«Chaque nouvelle version de Python sortira désormais en octobre. Python 3.10 sortira en octobre 2021, Python 3.11 en octobre 2022. Buckfix sortira tous les deux mois. C'est une excellente nouvelle pour moi, maintenant nous pouvons clairement planifier la mise à niveau de l'environnement python. "



PEP 584



Ce PEP suggère d'ajouter les opérateurs merge ( | ) et update ( | = ) à la classe dict intégrée.



Pour fusionner: |



>>> 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}


Pour mettre à jour: | =



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


La règle clé à retenir est qu'en cas de conflit de clé, la valeur la plus à droite sera conservée.



Bien sûr, de nombreux pythonistes auront une question, pourquoi est-ce nécessaire, s'il existe déjà une option familière à tout le monde



{**d1, **d2}


Cette question a été répondue dans le PEP lui-même:



Déballer des dictionnaires semble laid et n'est pas facile à détecter. Peu de gens pourront deviner ce que cela signifie lorsqu'ils le verront pour la première fois.


Comme l'a dit Guido :

Je m'excuse pour PEP 448 , mais même si vous connaissez ** d dans un contexte plus simple, si vous demandiez à un utilisateur Python typique comment combiner deux dict en un nouveau, je doute que beaucoup de gens pensent à {** d1, ** d2}. Je sais que je l'ai oublié moi-même quand ce fil a commencé!


De plus, {** d1, ** d2} ne fonctionne pas pour les sous-classes dict comme defaultdict




PEP 585



Conseils de type génériques dans les collections standard.



Le générique est un type paramétrable, une sorte de conteneur. Également appelé type paramétrique ou type générique.



Cette version inclut la prise en charge de la syntaxe universelle dans toutes les collections standard actuellement disponibles dans le module Typing. Nous pouvons utiliser des types list ou dict comme types génériques au lieu d'utiliser typing.List ou typing.Dict .



C'était:



from typing import List

a: List[str] = list()

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


Devenu:



a: list[str] = list()

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


Liste complète des types
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



Prise en charge de la base de données de fuseaux horaires IANA dans la bibliothèque standard.



Les fuseaux horaires de l'IANA sont souvent appelés tz ou informations de zone. Il existe un grand nombre de fuseaux horaires IANA avec différents chemins de recherche pour spécifier le fuseau horaire IANA pour un objet de date et d'heure. Par exemple, nous pouvons passer le nom du chemin de recherche Continent / City à un objet datetime pour définir son tzinfo.



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


Si nous passons la mauvaise clé, une exception sera levée

zoneinfo.ZoneInfoNotFoundError

PEP 616



Nouvelles fonctions de chaîne pour supprimer le préfixe et le suffixe. Deux nouvelles fonctions ont été ajoutées



à l' objet str .



  • La première fonction supprime le préfixe.
    str.removeprefix(prefix)
  • La deuxième fonction supprime le suffixe.
    str.removesuffix(suffix)


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


PEP 617



Python 3.9 propose de remplacer l'analyseur Python actuel basé sur LL (1) par un nouvel analyseur basé sur PEG qui est haute performance et stable.



L'analyseur CPython actuel est basé sur LL (1). Par la suite, la grammaire est basée sur LL (1), ce qui lui permet d'être analysée avec un analyseur LL (1). L'analyseur LL (1) fonctionne de haut en bas. De plus, il analyse les données d'entrée de gauche à droite. La grammaire actuelle est une grammaire sans contexte, donc le contexte des jetons n'est pas pris en compte.

Python 3.9 propose de le remplacer par un nouvel analyseur basé sur PEG, ce qui signifie qu'il supprimera les limitations actuelles de la grammaire LL de Python (1). De plus, des correctifs ont été apportés à l'analyseur actuel, ajoutant un certain nombre de hacks qui seront supprimés. En conséquence, cela réduira le coût de la maintenance à long terme.



Par exemple, alors que les analyseurs et les grammaires LL (1) sont faciles à implémenter, les contraintes les empêchent d'exprimer des constructions communes de manière naturelle pour le concepteur du langage et le lecteur. L'analyseur ne regarde qu'un seul jeton vers l'avant pour distinguer les possibilités.



issue30966



Possibilité d'annuler des contrats à terme simultanés .



Un nouveau paramètre cancel_futures a été ajouté à concurrent.futures.Executor.shutdown () .



Ce paramètre contient tous les futurs en attente qui n'ont pas encore démarré. Avant la version 3.9, le processus attendait leur fin avant de quitter l'exécuteur.



Un nouveau paramètre cancel_futures a été ajouté à ThreadPoolExecutor et ProcessPoolExecutor . Cela fonctionne lorsque la valeur du paramètre est True, alors tous les contrats à terme en attente seront annulés lorsque la fonction shutdown () est appelée .



Lors de l' arrêt ()est exécuté, l'interpréteur vérifie si l'exécuteur est ramassé. S'il est toujours en mémoire, il récupère tous les éléments en attente, puis annule les contrats à terme.



issue30966



Un certain nombre d'améliorations ont été apportées à la bibliothèque asyncio et multitraitement dans cette version.



Par exemple,



  1. Le paramètre reuse_address asyncio.loop.create_datagram_endpoint () n'est plus pris en charge en raison de problèmes de sécurité importants.
  2. Ajout de nouvelles coroutines, shutdown_default_executor () et asyncio.to_thread () . Un nouvel appel à asyncio.to_thread () est utilisé pour exécuter des fonctions liées aux E / S sur un thread séparé pour éviter de bloquer la boucle d'événements.


En ce qui concerne les améliorations apportées à la bibliothèque multitraitement, une nouvelle méthode close () a été ajoutée à la classe multiprocessing.SimpleQueue . Cette méthode ferme explicitement la file d'attente. Cela garantit que la file d'attente est fermée et ne reste pas plus longtemps que prévu. Il est important de se rappeler que les méthodes get (), put (), empty () ne peuvent pas être appelées après la fermeture de la file d'attente.







issue37444



Correction d'un bug avec l'importation de packages.



Le principal problème avec l'importation de bibliothèques Python avant la version 3.9 était le comportement d'importation incohérent dans Python lorsque les importations relatives passaient par son package de niveau supérieur.



builtins .__ import __ () a déclenché une ValueError tandis que importlib .__ import __ () a déclenché une ImportError.



Maintenant c'est corrigé . __Import __ () lève désormais ImportError au lieu de ValueError.



issue40286



Génération d'octets aléatoires.



Une autre fonctionnalité qui a été ajoutée dans la version 3.9 est random.Random.randbytes () . Il peut être utilisé pour générer des octets aléatoires.



Nous pouvons générer des nombres aléatoires, mais que faire si nous devions générer des octets aléatoires? Avant la version 3.9, les développeurs devaient être créatifs pour générer des octets aléatoires. Bien que nous puissions utiliser os.getrandom () , os.urandom () ou secrets.token_bytes (), nous ne pouvons pas générer de modèles pseudo-aléatoires.



Par exemple, pour garantir que les nombres aléatoires sont générés avec le comportement attendu et que le processus se reproduit, nous utilisons généralement des valeurs de départ avec le module random.Random.



En conséquence, la méthode random.Random.randbytes () a été introduite . Il génère des octets aléatoires.



issue28029



Correction de la fonction de remplacement de chaîne.



Le principe de la fonction replace est que pour un argument maximum donné pour remplacer une occurrence, elle remplace le jeu de caractères de la chaîne par le nouveau jeu de caractères.



Pour expliquer davantage le problème, avant la version 3.9, la fonction de remplacement avait un comportement incohérent:



on s'attendrait à voir le blog



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




On s'attendrait à voir |



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




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




issue39648, issue39479, issue39288, issue39310



Modifications dans le module "maths".



Renvoie le plus petit multiple commun d'arguments entiers:



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




Renvoie le plus grand diviseur commun d'arguments entiers. La version antérieure ne prenait en charge que deux arguments. Ajout de la prise en charge d'un nombre arbitraire d'arguments:



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




Calcule le nombre à virgule flottante le plus proche de " x " dans la direction de " y ".



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




Cette méthode renvoie la valeur du bit le moins significatif du nombre à virgule flottante x.



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




problème38870



La méthode unparse a été ajoutée au module ast.

La nouvelle méthode peut être utilisée pour créer une ligne de code puis l'exécuter.



>>> 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




issue39507, issue39509



Ajout de nouveaux codes à http.HTTPStatus.



" Économisez 418! "

418 IM_A_TEAPOT
103 EARLY_HINTS
425 TOO_EARLY




UPD :

PEP 614



Assouplissement des restrictions grammaticales pour les décorateurs.



C'était:



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():
    ...


Vous pouvez désormais supprimer les affectations inutiles et appeler directement:



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

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

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




«Le tuple doit être placé entre parenthèses.»



Ceci est basé sur la vision de Guido dans la même lettre. Citation:



Mais je n'autoriserai pas les virgules. Je ne peux pas être d'accord avec ça



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


Cela peut conduire les programmeurs inexpérimentés à la conclusion que plusieurs décorateurs peuvent être appelés de cette manière. Les parenthèses sont nécessaires pour tout clarifier sans restrictions supplémentaires ni syntaxe complexe.




issue17005



Le nouveau module graphlib fournit des fonctionnalités pour le tri topologique d'un graphe de nœuds hachés.

Plus de détails peuvent être trouvés dans la documentation .



UPD :ifinik

image



>>> 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')


Le graphe peut être transféré non immédiatement, mais remplissez le TopologicalSorter en utilisant la méthode add . De plus, la classe est adaptée au calcul parallèle et peut être utilisée, par exemple, pour créer une file d'attente de tâches.



issue37630, issue40479



Mise à jour de la bibliothèque hashlib.

Hashlib peut désormais utiliser les hachages SHA3 et SHAKE XOF d'OpenSSL.

Les modules de hachage intégrés peuvent désormais être désactivés ou activés de manière sélective, par exemple pour appliquer une implémentation basée sur OpenSSL.



Optimisation



Un résumé des améliorations de performances de Python 3.4 à 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


Le script de test affiche l'heure en nanosecondes. Les tests ont été réalisés sur un processeur Intel Core i7-4960HQ . Le code de test se trouve dans le référentiel sous " Tools / scripts / var_access_benchmark.py " .



Merci de votre attention.



Lien vers le manuel officiel de Python 3.9.

Désabonnez-vous dans les commentaires si vous avez manqué quelque chose.



All Articles