IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

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

Le , par Stéphane le calme

221PARTAGES

13  0 
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 Python : Sélectionner tout
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 Python : Sélectionner tout
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 Python : Sélectionner tout
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=Python]>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime, timedelta

>>> # Daylight saving time
>>> dt = datetime(20[/code=python]...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de transgohan
Expert éminent https://www.developpez.com
Le 06/10/2020 à 15:40
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().
Merci mille fois !
J'en ai l'utilité dans un projet et je dois systématiquement enregistrer la valeur de __file__ dans une variable avant d'exécuter une action qui pourrait avoir le malheur de faire un chdir...
Cela me paraît tellement aberrant de faire ainsi...
1  0 
Avatar de Fagus
Membre expert https://www.developpez.com
Le 07/10/2020 à 11:03
{** d1, ** d2} : peu de gens seraient capables de deviner ce que cela signifie la première fois qu'ils le voient,
Étrange choix en effet, on dirait une sorte de liste de pointeurs de pointeurs.
0  0