La .Taverne de l'Invisible

Une page de Le Lab de la taverne

Tout savoir sur l'inversion de chaîne en Python

Par Darko Stankovski, 23/11/2019 (Mise à jour 13/03/2026) — Débutant

Tout débutant en Python s'est un jour étonné de ne pas trouver de manière simple pour inverser le contenu d'une chaine de caractères. Avec les listes, il a vu la méthode .reverse() mais elle n'existe pas pour les chaînes de caractères. Et c’est normal… La méthode list.reverse() inverse la liste, elle modifie la donnée. Les chaînes de caractères étant immuables, ce n’est donc pas possible.

Alors dans cet article on va voir la manière pour inverser une chaine de caractères. Non, il n’y a pas 5 méthodes pour inverser une chaîne de caractères, Zen de Python nous rappelle qu’il ne devrait y avoir qu’une, et de préférence une seule, manière évidente de faire les choses.

Comment inverser une chaine de caractères en Python ?

L’outil, vous le connaissez certainement déjà : c’est le slicing ! Si vous le connaissez pas, commencez par cet article que je lui ai dédié.

Le code est aussi simple que :

>>> 'abc'[::-1]                                                            
'cba'

Et voilà… C’est tout. Et c'est la manière la plus pythonique.

Le slicing s'applique à toute séquence (les chaines de caractères sont des séquences). Cette expression retourne une une nouvelle donnée, la chaine initiale n’est évidemment pas modifiée (impossible puisqu’immuable).

Pourquoi n'y a-t-il pas de méthode reverse() ?

L'absence de la méthode reverse() que l'on trouve pour les listes s’explique par le fait qu'il serait attendu le même comportement. Or la méthode reverse() inverse la liste elle-même et ne retourne rien. Ce qui n'est pas possible avec une chaine de caractères puisqu'elle est immuable.

Ce que vous ne devez pas faire et pourquoi

Parce que disons le, ça marche… Le pourquoi, c'est de la performance.

En faisant un timeit sur le slicing avec la chaine "Then shalt thou count to three, no more, no less. Three shall be the number thou shalt count, and the number of the counting shall be three.", j'obtiens sur ma machine un résultat de 127 ns ± 1.7 ns.

la fonction reversed()

La fonction  reversed(seq) est une fonction built-in qui prend en paramètre une séquence et retourne un itérateur.

>>> reversed('abc')
<reversed at 0x1050cfa30>

Nous pouvons donc itérer sur cet objet :

>>> for c in reversed('abc'):
...     print(c)
... 
c
b
a

Donc pour obtenir une chaine inversée, nous pouvons concaténer le retour de la manière suivante :

>>> "".join(reversed('abc'))
'cba'

À priori, ça fait le job. Et on voit souvent ce code dans les tutos sur le web. Mais coté performance, avec la même séquence que précédemment, le timeit me donne 1.25 μs ± 9.86 ns. C'était 127 ns ± 1.7 ns avec le slicing.

L'itération classique

Parfois, on trouve comme proposition des fonctions de ce type :

def rev(chaine):    
    r = ""
    for c in chaine:
        r = c + r
    return r

Là aussi, elle fait le job. Mais coté performance, toujours avec la même chaine, le timeit m'indique 4.55 μs ± 32 ns. C'est encore pire. Et c'est normal vu que la concaténation est moins efficace que le join().

N'oublions pas le typage canard

Une autre raison pour n'utiliser que le slicing est le Duck Typing. Python utilise abondamment le principe du Duck Typing, ce fameux typage canard.

En Python, on ne va pas s’intéresser au type de la donnée mais à ce qu’elle peut faire. Le code avec le slicing fonctionne avec toute séquence (toute collection ordonnée) et plus généralement avec tout type compatible avec le slicing. Les deux autres ne fonctionne qu’avec les chaines de caractères.

Si dans votre code vous devez inverser une séquence qui peut être une chaine de caractères mais peut-être des fois une liste ou un tuple, alors l'expression avec le slicing passera mais pas les deux autres.

Mais le slicing a un défaut !

Et ce défaut, c'est que les graphèmes ne passent pas. Un graphème, c'est un caractère composé de plusieurs caractères combinés. Vous ne voyez pas ces caractères combinés, vous ne voyez que le résultat qui est certains caractères accentués ou certains émojis comme 👨‍👩‍👧. Quel est alors le comportement ? Voyons :

>>> "👨‍👩‍👧"[::-1]
'👧\u200d👩\u200d👨'

Ce qu'a fait Python, c'est qu'il a inversé les caractères composants. Oui, cet émoji est composé de 5 caractères (faites un len("👨‍👩‍👧") pour vérifier) : 3 émojis liés par le caractère Zero Width Joiner qui est un caractère invisible destiné à coller les autres.

La limite du slicing est qu'il inverse tous les caractères unitaires de la chaine. Sa limite d'usage est donc le contenu de la chaine que vous devrez traiter. Pour les données textuelles complexes, allez voir la bibliothèque grapheme.

En conclusion

Il n'y a réellement qu'une méthode pour inverser une chaine de caractères : le slicing. C’est fait pour, c’est performant, c'est pythonique et ça s’applique à toute séquence. Avec certes la limite des données textuelles complexes mais si vous devez en rencontrer, vous le saurez.

Licence Creative Commons

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