La .Taverne de l'Invisible

Une page de Le Lab de la taverne

Maitrisez le walrus operator (:=) en Python

Par Darko Stankovski, 10/02/2020 (Mise à jour 11/03/2026) — Intermediaire

La mise à jour 3.8 de Python a ajouté une nouvelle syntaxe d’assignation, le walrus operator ou en français, opérateur walrus, noté :=. Pour ceux qui ne parlent pas anglais, walrus, c’est un morse. L’opérateur a été nommé ainsi pour sa ressemblance avec les yeux et les défenses du morse.

Le walrus operator permet d’assigner une valeur à une variable dans une expression plus globale. La définition étant posée, voyons ce que ça donne en pratique.

Un cas pratique

Il est assez commun que nous ayons à récupérer des données d’un appel de fonction (ou toute autre instruction) pour par exemple la tester et, si le test est positif, l’utiliser par la suite. Il y a alors deux types de codes.

Le code correspondant à cette intention est par exemple le suivant.

if len(my_collection) > 10:
    print(f"Vous avez {len(my_collection)} éléments")

Ce code a deux défauts. Le premier est qu’il fait appel deux fois à la fonction avec un second traitement finalement inutile. Si ce traitement est long, cela peut avoir un impact sur l’exécution. Le second est que si la fonction appelée n’est pas déterministe, il y aura une différence entre la donnée testée et la donnée utilisée.

Le walrus operator

Le walrus operator veut simplifier cette écriture en permettant d’affecter ce retour à une variable dans l’instruction du test. Le code devient donc le suivant.

if (size := len(my collection)) > 10:
    print(f"Vous avez {size} éléments")

Attention à la parenthèse, si vous l’oubliez, c’est le retour de la comparaison que vous affecterez à la variable.

Alors bien sûr, il est possible de se passer de cet opérateur en affectant la donnée à la variable avant l’instruction comme dans le code suivant.

size = len(my_collection)
if size > 10:
    print(f"Vous avez {size} éléments")

Par rapport à ce type de code, l’intention est de faciliter la lisibilité. Lorsque nous le plaçons dans un contexte plus global, nous découvrons une création de variable avant de comprendre l’usage (test et utilisation). Le walrus operator a donc comme objectif de faire comprendre l’intention d’usage de cette variable, de réduire la complexité du code.

Rendre un code plus lisible

L’objectif du walrus operator est bien de rendre le code plus lisible en réduisant la complexité. Il existe de nombreux cas plus spécifiques où l’intérêt est plus évident.

Les expressions rationnelles

Prenons le cas des expressions rationnelles pour lesquels il est indispensable de tester le retour (qui peut être None si aucun résultat n’a été trouvé) avant de l’exploiter. Ainsi, au lieu d’écrire :

import re
result = re.search("chat", "un chat noir")
if result:
    print(result.start())

Nous allons pouvoir écrire :

import re
if result := re.search("chat", "un chat noir"):
    print(result.start())

L'itération sur des slices

Dans mon article sur le slicing, je vous ai proposé un exemple de code combinant l’opérateur while et le walrus operator permettant de parcourir une collection tant qu’il y a un élément.

>>> size = 2
>>> start = 0
>>> while group := camelot[start:start + size]:
...     print(group)
...     start += size
... 
['Arthur', 'Lancelot']
['Robin', 'Galahad']
['Bedivere', 'Perceval']
>>>

Et un cas plus poussé…

Prenons le cas où vous devez écrire une fonction d'analyse de texte (une chaine passée en argument) et qui retourne un dictionnaire contenant :

  • la liste de tous les mots
  • le nombre de mots
  • la longueur moyenne des mots.

La fonction pourrait-être la suivante :

def text_analysis(text: str) -> dict:
    words = text.split()
    words_count = len(words)
    avg_word_len = round(sum((len(word) for word in words)) / words_count)

    return {'words': words,
            'words_count': words_count,
            'avg_word_count': avg_word_count}

Et bien ça peut se simplifier de la manière suivante…

def text_analysis(text: str) -> dict:
    return {'words': (words := text.split()),
            'words_count': (words_count := len(words)),
            'avg_word_count': round(sum((len(word) for word in words)) / words_count)}

Honnêtement, je ne suis pas certain qu'on y gagne vraiment quelque chose mais c'est intéressant d'avoir un opérateur qui permette d'utiliser un résultat dans une même structure.

Pour une présentation plus visuelle

J’ai présenté le Walrus Operator lors d’un meetup en ligne sur les nouveautés de Python 3.8, vous pouvez le voir dans la vidéo suivante

En conclusion

Le Walrus Operator, que l'on traduit parfois Opérateur Walrus, a comme objectif principal d’améliorer la lisibilité du code en réduisant la complexité. Ce n’est peut-être pas une instruction révolutionnaire et je pense que les habitudes font qu’elle mettra du temps avant d’être utilisée. Mais il y a déjà des cas d’usage où cet opérateur va permettre une meilleur interprétation du code.

Licence Creative Commons

Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Pas de Modification 4.0 International