Python 3.9 est disponible et s'accompagne de l'ajout des opérateurs "|" et "| =" aux dictionnaires
Python 3.9, la prochaine version du langage Python : construction des types génériques dans les collections standard,
et un analyseur PEG pour CPython
Python 3.8 a été publié en octobre dernier et les travaux sur la version 3.9 du langage ont déjà commencé. Python 3.9 est prévue pour arriver en octobre 2020, mais des aperçus sont déjà disponibles et permettent d’avoir une idée brève des fonctionnalités et des améliorations qui pourraient être introduites dans cette version. La dernière version alpha, la 3.9.0a6, a été publiée vers la fin du mois d’avril et apporte des fonctionnalités qui, pour la plupart, rendront le code Python plus propre. Voici certaines des choses auxquelles l’on peut s’attendre dans Python 3.9.
Avant d’aller plus loin dans le sujet, il est important de noter que les versions mineures précédentes de Python 3 contenaient encore quelques fonctions pour la rétrocompatibilité avec Python 2.7. Mais depuis l'arrêt officiel du support de Python 2.7 et à partir de Python 3.9, de nombreuses fonctions seront supprimées ou seront marquées comme obsolètes. Il s’agit d’une information à prendre en compte lorsque vous souhaiteriez passer de la version 2.7 à la version 3.9. Les différences notables entre Python 3.8 et les versions alpha de Python 3.9 publiées sont :
Construire des types génériques dans les collections standard
Si vous avez travaillé avec les langages Java ou C#, vous connaissez la notion de types génériques. Ce sont généralement des collections qui peuvent être paramétrées avec le type qu'elles contiennent. Par exemple, en C#, vous pouvez définir une liste comme celle-ci : var exampleList = new List<string>(). Ce qui signifie que vous créez une liste de chaînes de caractères.
Maintenant, Python introduit ce genre de fonctionnalité dans le module de saisie. Fondamentalement, les outils ainsi que les vérificateurs de type et les linters sont modifiés pour reconnaître les collections standard comme des types génériques. Cela signifie que vous n'avez pas besoin d'importer les types en majuscules correspondants (par exemple, List) à la saisie. En bref, cette fonctionnalité supprime la nécessité d'une hiérarchie de types parallèle dans le module de saisie et facilite les annotations du programme.
Analyseur PEG
Cette nouvelle fonctionnalité n'affecte pas autant les développeurs. Cela pourrait être intéressant pour les ingénieurs qui s'intéressent aux compilateurs. Jusqu'à présent, Python utilisait un analyseur basé sur LL(1) et toute la grammaire Python était en quelque sorte construite autour de cet analyseur. L'analyseur LL(1) est un analyseur descendant qui analyse l'entrée de gauche à droite.
Tout d'abord, il effectue une dérivation de la phrase vers la gauche, avec un seul jeton de regard. Il crée ainsi un tableau qui contient des transitions codées entre tous les états possibles de l'analyseur, le tableau d'analyse. En raison de la nature de Python et des limitations de LL(1), certains hacks ont été introduits dans le langage. C'est pour cela qu’un nouvel analyseur basé sur le PEG (Parsing Expression Grammar) est utilisé dans Python 3.9. La différence entre la grammaire PEG et LL(1) est que la grammaire PEG reflète la manière dont l'analyseur fonctionnera lors de l'analyse.
Ordre topologique
Si vous travaillez avec des graphiques, alors vous allez trouver cette fonctionnalité intéressante et utile. Une nouvelle classe TopologicalSorter est ajoutée au module functools. Cette classe effectue l'ordonnancement topologique du graphique. Pour faire quelque chose comme cela avec les versions précédentes de Python, vous devriez l'implémenter vous-même en vous servant des algorithmes comme une recherche en profondeur ou l'algorithme de Khan. Un autre avantage de cette fonctionnalité est qu'elle permet le tri parallèle des nœuds, même s'ils sont ajoutés un par un.
Dans ce cas, vous créez TopologicalSorter avec un graphe initial optionnel et vous ajoutez ensuite des nœuds supplémentaires au graphe. Vous utiliserez les méthodes prepare, is_active et get_ready pour traiter chaque nœud, puis vous utiliserez la méthode done pour indiquer que le nœud est ajouté et que le graphe est trié.
Nouvelles méthodes de calcul et d'analyse des chaînes de caractères
Des modules tels que les chaînes de caractères et les mathématiques sont également étendus avec quelques fonctions utiles en Python 3.9. Le module string a deux nouvelles méthodes : removeprefix et removesuffix. Celles-ci permettent de supprimer facilement un préfixe ou un suffixe inutile d'une chaîne de caractères. Les modules bytes, bytearray, et collections.UserString sont étendus avec les mêmes méthodes. D’autres méthodes comme math.gdc et math.ldc, pour calculer respectivement le plus grand diviseur commun et le plus petit multiple commun, sont maintenant étendues de sorte qu'elles reçoivent plus de deux paramètres.
En outre, de nouvelles méthodes ont été ajoutées au module mathématique :
- nextafter(a, b) qui retourne le prochain nombre flottant après a allant vers b ;
- ulp(a) qui retourne la valeur du bit le moins significatif d'un flottant. ULP signifie “Unit in the Last Place” et est utilisé comme mesure de précision dans les calculs numériques ;
- etc.
Il ne s’agit là que de quelques fonctionnalités prévues pour être livrées avec Python 3.9. Certaines de ces fonctionnalités se traduisent par un code plus propre et plus compréhensible, tandis que d'autres pourraient recadrer l’état d'esprit sur la grammaire Python. Vous pouvez vous référer à la documentation officielle pour en savoir plus sur ces diverses fonctionnalités et voir ce que la nouvelle version apporte d'autre.
Sources : Python 3.9.0a5, Python 3.9.0a6
Et vous ?
:fleche: Que pensez-vous des nouveautés prévues pour Python 3.9 ?
:fleche: Quelles autres fonctionnalités souhaiteriez-vous avoir dans Python 3.9 ?
Voir aussi
:fleche: Python 3.8.0 est publié avec la prise en charge des expressions d'affectation (l'opérateur de morse « := ») et les paramètres de position uniquement
:fleche: Python 3.8.0 : la première version bêta est publiée avec une API C pour améliorer la configuration de l'initialisation
:fleche: Une première version alpha de Python 3.8 est publiée. Voici un tour d'horizon des nouveautés de cette version
2 pièce(s) jointe(s)
Python 3.9 est disponible et s'accompagne de l'ajout des opérateurs "|" et "| =" aux dictionnaires
Python 3.9 est disponible et s'accompagne de l'ajout des opérateurs "|" et "| =" aux dictionnaires,
ainsi que de la possibilité de construire des types génériques dans les collections standard
L'équipe en charge du développement du langage a annoncé la disponibilité de Python 3.9. Passons en revue quelques nouvelles fonctionnalités.
Nouvelles fonctionnalités
Ajout des opérateurs | et | = à dict
À partir des types de base (int, float, etc.) il est possible d’élaborer de nouveaux types qu’on appelle des types construits. Parmi les exemples de type construit figure le dictionnaire.
Les éléments d’une liste ou d’un tuple sont ordonnés et il est possible d'accéder à un élément grâce à sa position en utilisant un numéro qu’on appelle l’indice de l’élément. Un dictionnaire en Python va aussi permettre de rassembler des éléments, mais ceux-ci seront identifiés par une clé. On peut faire l’analogie avec un dictionnaire de français où on accède à une définition avec un mot.
Contrairement aux listes qui sont délimitées par des crochets, on utilise des accolades pour les dictionnaires.
Selon les responsables, les méthodes actuelles de fusion de deux dictionnaires présentent plusieurs inconvénients:
- dict.update : d1.update(d2) modifie d1 sur place. e = d1.copy(); e.update(d2) n'est pas une expression et nécessite une variable temporaire
- {** d1, ** d2} : peu de gens seraient capables de deviner ce que cela signifie la première fois qu'ils le voient, ou de le considérer comme la "manière évidente" de fusionner deux dictionnaires. De plus, {**d1, **d2} ignore les types des mappings et retourne toujours un dict. type(d1)({**d1, **d2}) ne fonctionne pas pour les sous-classes dict comme defaultdict qui a une __init__ method incompatible.
Aussi, dans cette version, les opérateurs de fusion (|) et de mise à jour (| =) ont été ajoutés à la classe dict intégrée. Ceux-ci viennent compléter les méthodes existantes dict.update et {** d1, ** d2} de fusion.
Exemple:
Code:
1 2 3 4 5 6
| >>> x = {"key1": "value1 from x", "key2": "value2 from x"}
>>> y = {"key2": "value2 from y", "key3": "value3 from y"}
>>> x | y
{'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}
>>> y | x
{'key2': 'value2 from x', 'key3': 'value3 from y', 'key1': 'value1 from x'} |
Nouvelles méthodes de chaîne pour supprimer les préfixes et les suffixes
str.removeprefix(prefix) et str.removesuffix(suffix) ont été ajoutés pour supprimer facilement un préfixe inutile ou un suffixe d'une chaîne. Les méthodes correspondantes bytes, bytearray, et collections.UserString ont aussi été ajoutées.
Sur des forums de discussion, plusieurs développeurs ont signalé être confus au sujet des méthodes str.lstrip et str.rstrip existantes. Ces développeurs s'attendent généralement au comportement de removeprefix et de removesuffix, mais ils sont surpris que le paramètre de lstrip soit interprété comme un ensemble de caractères et non comme une sous-chaîne. Ce problème signalé à plusieurs reprises semble indiquer que ces méthodes sont utiles. Les nouvelles méthodes permettent une redirection plus nette des utilisateurs vers le comportement souhaité.
La classe str intégrée gagnera deux nouvelles méthodes qui se comporteront comme suit :
Code:
1 2 3 4 5 6 7 8 9 10 11 12
| def removeprefix(self: str, prefix: str, /) -> str:
if self.startswith(prefix):
return self[len(prefix):]
else:
return self[:]
def removesuffix(self: str, suffix: str, /) -> str:
# suffix='' should not call self[:-0].
if suffix and self.endswith(suffix):
return self[:-len(suffix)]
else:
return self[:] |
Lorsque les arguments sont des instances de sous-classes str, les méthodes doivent se comporter comme si ces arguments avaient d'abord été forcés à des objets str de base, et la valeur de retour doit toujours être une str de base.
Les méthodes avec la sémantique correspondante seront ajoutées aux objets intégrés bytes et bytearray. Si b est un objet bytes ou bytearray, alors b.removeprefix() et b.removesuffix() accepteront tout objet de type bytes comme argument. Les deux méthodes seront également ajoutées aux collections.UserString, avec un comportement similaire.
Construction des types génériques dans les collections standard
Si vous avez travaillé avec les langages Java ou C#, vous connaissez la notion de types génériques. Ce sont généralement des collections qui peuvent être paramétrées avec le type qu'elles contiennent. Par exemple, en C#, vous pouvez définir une liste comme celle-ci : var exampleList = new List<string>(). Ce qui signifie que vous créez une liste de chaînes de caractères.
Maintenant, Python introduit ce genre de fonctionnalité dans le module de saisie. Fondamentalement, les outils ainsi que les vérificateurs de type et les linters sont modifiés pour reconnaître les collections standard comme des types génériques. Dans les annotations de type, vous pouvez désormais utiliser des types de collections intégrés tels que list et dict comme types génériques au lieu d'importer les types en majuscules correspondants (par exemple, List ou Dict) à partir de typing. Certains autres types de la bibliothèque standard sont également désormais génériques, par exemple queue.Queue. En bref, cette fonctionnalité supprime la nécessité d'une hiérarchie de types parallèle dans le module de saisie et facilite les annotations du programme.
Exemple :
Code:
1 2 3
| def greet_all(names: list[str]) -> None:
for name in names:
print("Hello", name) |
Nouvel analyseur
Python 3.9 utilise un nouvel analyseur, basé sur PEG au lieu de LL(1). Les performances du nouvel analyseur sont à peu près comparables à celles de l'ancien analyseur, mais le formalisme PEG est plus flexible que LL(1) lorsqu'il s'agit de concevoir de nouvelles fonctionnalités de langage. L'équipe fera appel à cette flexibilité à partir de Python 3.10.
Le module ast utilise le nouvel analyseur et produit le même AST que l'ancien analyseur.
Dans Python 3.10, l'ancien analyseur sera supprimé, de même que toutes les fonctionnalités qui en dépendent (principalement le module parser, qui est obsolète depuis longtemps). Dans Python 3.9 uniquement, vous pouvez revenir à l'analyseur LL(1) à l'aide d'un switch en ligne de commande (-X oldparser) ou d'une variable d'environnement (PYTHONOLDPARSER=1).
Autres changements au niveau du langage
- __import__() lance désormais ImportError au lieu de ValueError, qui se produisait auparavant lorsqu'une importation relative dépassait son package de niveau supérieur.
- Python obtient maintenant le chemin absolu du nom de fichier du script spécifié sur la ligne de commande (ex. : python3 script.py): l'attribut __file__ du module __main__ est devenu un chemin absolu, plutôt qu'un chemin relatif. Ces chemins restent désormais valides après la modification du répertoire courant par os.chdir().
- "".replace("", s, n) retourne désormais s au lieu d'une chaîne de caractère vide pour tout n non vide.
Nouveaux modules
zoneinfo
Le module zoneinfo apporte la prise en charge de la base de données de fuseaux horaires IANA à la bibliothèque standard. Il ajoute zoneinfo.ZoneInfo, une implémentation concrète datetime.tzinfo soutenue par les données de fuseau horaire du système.
Exemple :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| >>> from zoneinfo import ZoneInfo
>>> from datetime import datetime, timedelta
>>> # Daylight saving time
>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-10-31 12:00:00-07:00
>>> dt.tzname()
'PDT'
>>> # Standard time
>>> dt += timedelta(days=7)
>>> print(dt)
2020-11-07 12:00:00-08:00
>>> print(dt.tzname())
PST |
graphlib
Un nouveau module, graphlib, a été ajouté qui contient la classe graphlib.TopologicalSorter pour offrir des fonctionnalités pour effectuer le tri topologique des graphiques.
Modules améliorés
ast
Ce module s'accompagne de :
- l'ajout d'une option indent à dump() qui lui permet de produire une sortie indentée multiligne ;
- l'ajout de ast.unparse() comme fonction dans le module qui peut être utilisée pour décompresser (unparse) un objet ast.AST et produire une chaîne avec du code qui produirait un objet ast.AST équivalent lors de l'analyse ;
- l'ajout de docstrings aux nœuds AST contenant la signature ASDL utilisée pour construire ce nœud.
asyncio
- En raison de problèmes de sécurité importants, le paramètre reuse_address de asyncio.loop.create_datagram_endpoint() n'est plus pris en charge. Cela est dû au comportement de l'option de socket SO_REUSEADDR dans UDP.
- Ce module s'accompagne de l'ajout d'une nouvelle coroutine shutdown_default_executor() qui planifie un arrêt de l'exécuteur par défaut qui attend que ThreadPoolExecutor termine sa fermeture. De plus, asyncio.run() a été mis à jour pour utiliser la nouvelle coroutine.
- L'ajout de asyncio.PidfdChildWatcher, une implémentation de l'observateur enfant spécifique à Linux qui interroge les descripteurs de fichier de processus.
- Ajout d'une nouvelle coroutine asyncio.to_thread(). Elle est principalement utilisée pour exécuter des fonctions liées aux E / S dans un thread séparé pour éviter de bloquer la boucle d'événements, et fonctionne essentiellement comme une version de haut niveau de run_in_executor() qui peut directement prendre des arguments de mot-clé.
Source : note de version
Voir aussi :
:fleche: La popularité de Java continue de décliner et profite à Python qui se rapproche de plus en plus de la seconde place, selon l'édition d'octobre 2020 de l'index TIOBE
:fleche: Microsoft annonce Playwright pour le langage Python, permettant de tester les applications Web et qui fonctionne dans tous les principaux navigateurs
:fleche: Toutes les versions de Python inférieures à 3.6 sont maintenant en fin de vie, la version 3.9 sera livrée en octobre prochain et la version 3.10 un an après