Découvrez les nouveautés de Python 3.8

By Nasser

5 min read

:::

Cet article a été publié en tant que thread sur twitter par Elias Walyba, data scientist et machine learner au Sénégal. Néanmoins, j'ai retouché quelques mots.

::: {.separator style="clear: both; text-align: center;"} :::

Python 3.8 est sorti le 14 octobre dernier. Cette nouvelle version de Python vient avec quelques fonctionnalités plutôt intéressantes en terme de développement. Dans ce thread je vous présente quelques unes de ces fonctionnalités que j’ai eu à tester.

1/ L’opérateur de warlus «:=»

Cet opérateur vous permet de faire des assignation de valeurs à des variables dans des expressions ou des blocs d’expressions. Son signe est := . Il est très utile pour éviter de se répéter dans des structures de contrôles.

[# Le bout de code suivant (3.7):]{style="font-family: "courier new" , "courier" , monospace;"}
[if len(dataset) > 1000:]{style="font-family: "courier new" , "courier" , monospace;"}
[ print(f’’moins de {len(dataset)} éléments attendus’’)]{style="font-family: "courier new" , "courier" , monospace;"}
[
]{style="font-family: "courier new" , "courier" , monospace;"}[# Devient (3.8):]{style="font-family: "courier new" , "courier" , monospace;"}
[if (n:=len(dataset)) > 1000:]{style="font-family: "courier new" , "courier" , monospace;"}
[ print(f’’moins de {n} éléments attendus’’)]{style="font-family: "courier new" , "courier" , monospace;"}

2/ Les paramètre «/» et «*» des fonctions

Cette version de Python introduit ce qu’ils appellent: positional-only parameter et qui se note /. Cette fonctionnalités permet de dire que certains paramètres d’une fonction (ou méthode) ne peuvent être passés que par position et pas par clé-valeur. Elle introduit aussi le keywords only parameter qui se note * qui lui permet de dire que certains paramètres ne peuvent être passés que par clé-valeur.

Dans la fonction suivante, a et b ne peuvent être passé que par position, ce qui peut être à la fois passé par position et par clé-valeur et d ne peut être passé que par clé-valeur.

[def func(a, b, /, c, \*, e):]{style="font-family: \"courier new\" , \"courier\" , monospace;"}  

[ pass]{style="font-family: "courier new" , "courier" , monospace;"}

[func(2, 5, c=40, e=1.7)]{style="font-family: "courier new" , "courier" , monospace;"}

ou

[func(2, 5, 40, e=1.7)]{style="font-family: "courier new" , "courier" , monospace;"}

Cette fonctionnalité est très utile pour écrire du code avec le paradigme fonctionnel.

3/ Ajout du signe «=» dans les f-strings

L’autre fonctionnalité super sympa de cette version c’est l’ajout du signe = dans les f-strings pour faciliter l’inspection de variable et la self documentation.
La f-string suivante: [f"{expr=}"]{style="font-family: "courier new" , "courier" , monospace;"} produit la chaine ["expr=valeur_de_expr"]{style="font-family: "courier new" , "courier" , monospace;"}

Le code suivant:
[twitto = "]{style="font-family: "courier new" , "courier" , monospace;"}[@eliaswalyba]{style="font-family: "courier new" , "courier" , monospace;"}["]{style="font-family: "courier new" , "courier" , monospace;"}
[age = 26]{style="font-family: "courier new" , "courier" , monospace;"}
[print(f"{twitto=} {age=}")]{style="font-family: "courier new" , "courier" , monospace;"}

Produit:
["twitto=]{style="font-family: "courier new" , "courier" , monospace;"}[@eliaswalyba ]{style="font-family: "courier new" , "courier" , monospace;"}[age=26"]{style="font-family: "courier new" , "courier" , monospace;"}

PS: On peut l’utiliser avec les formatages de f-strings pour plus de contrôle.

[print(f'{theta=} {cos(radians(theta))=:.3f}')]{style="font-family: "courier new" , "courier" , monospace;"}
[theta=30 cos(radians(theta))=0.866]{style="font-family: "courier new" , "courier" , monospace;"}

4/ Plus de précision sur le typage

Avec l’introduction de types de données tels que:

  • Literal types
  • Type dictionaries
  • Final objects
  • Protocols

Python prend en charge les indicateurs de type facultatifs, généralement sous forme d'annotations sur le code:

[def double(number: float) -> float:]{style="font-family: "courier new" , "courier" , monospace;"}
[ return 2 * number]{style="font-family: "courier new" , "courier" , monospace;"}

Dans cet exemple, [**number **]{style="font-family: "courier new" , "courier" , monospace;"}doit être un float et la fonction double() doit également renvoyer un float. Cependant, Python traite ces annotations comme des astuces. Ils ne sont pas appliqués à l'exécution:

[double(2)]{style="font-family: "courier new" , "courier" , monospace;"}
retorune 4

[double("Dakar)]{style="font-family: "courier new" , "courier" , monospace;"}
retourne DakarDakar

Même si cela ne permet pas de faire de Python un langage à typage statique et fort, ça a une réelle importance pour les programmes de type-checking tels que mypy qui pourront l’utiliser pour faire du type-checking avant ou lors de l’édition.

Les types Literal, Protocoles, etc sont accessible via le package typing.

[from typing import Literal]{style="font-family: "courier new" , "courier" , monospace;"}

5. La fonction reversed() sur les dictionnaires

Depuis Python 3.7, les dictionnaires conservent l'ordre d'insertion des clés. Avec Python 3.8 [reversed()]{style="font-family: "courier new" , "courier" , monospace;"} peut maintenant être utilisé pour accéder au dictionnaire dans l'ordre inverse de l'insertion - exactement comme [OrderedDict]{style="font-family: "courier new" , "courier" , monospace;"}

6. L’unpacking avec return et yield

Depuis Python 3.2, l’unpacking des éléments itérables sans parenthèses dans les instructions [return ]{style="font-family: "courier new" , "courier" , monospace;"}et [yield ]{style="font-family: "courier new" , "courier" , monospace;"}est interdit:

[# interdit]{style="font-family: "courier new" , "courier" , monospace;"}
[def func():]{style="font-family: "courier new" , "courier" , monospace;"}
[ res = (4, 5, 6)]{style="font-family: "courier new" , "courier" , monospace;"}
[ return 1, 2, 3, *res]{style="font-family: "courier new" , "courier" , monospace;"}
[
]{style="font-family: "courier new" , "courier" , monospace;"}[def func():]{style="font-family: "courier new" , "courier" , monospace;"}
[ res = (4, 5, 6)]{style="font-family: "courier new" , "courier" , monospace;"}
[ yield 1, 2, 3, *res]{style="font-family: "courier new" , "courier" , monospace;"}

Toutes les deux fonctions renvoyaient des [SyntaxError]{style="font-family: "courier new" , "courier" , monospace;"}
Avec Python 3.8, ce truc a été corrigé et donc possible maintenant.

7. Syntax Warning

Python 3.8 permet de faire des alertes en cas d’erreurs de syntaxe dans certains cas.

Le code suivant:
[data = []{style="font-family: "courier new" , "courier" , monospace;"}
[ (1, 2, 3) # absence de virgule]{style="font-family: "courier new" , "courier" , monospace;"}
[ (4, 5, 6)]{style="font-family: "courier new" , "courier" , monospace;"}
[]]{style="font-family: "courier new" , "courier" , monospace;"}

Au lieu de générer l’erreur: [TypeError: 'tuple' object is not callable]{style="font-family: "courier new" , "courier" , monospace;"} qui est une horreur 😱🤯, vous avez maintenant une Syntax Warning qui vous dit que vous avez probablement oublié une virgule. C’est qui est beaucoup mieux pour le débogage.

Voilà c’est tout ce que j’avais à partager avec vous concernant les nouvelles fonctionnalités de Python. Je suis sûr que vous allez les adorer 😍. Pour ma part je ne les trouve pas très nombreuses mais je pense qu’elles sont supers utiles et arrivent au bon moment.

Pour plus de détail vous pouvez consulter la documentation de Python dans la partie Whatsnew ou bien le blog realpython

Merci à Elias Walyba sans qui cet article aurait été beaucoup moins sympa à lire !

:::
</p>