Comment marchent les “raw strings” en Python ?
Dans certains tutos, notamment ceux sur les expressions rationelles, on recommande d’utiliser les “raw strings”, en mettant un “r” devant la déclaration de la chaîne de caractères.
Par exemple:
'1?\d\d?'
Devient:
r'1?\d\d?'
A quoi cela sert-il ?
Voyons d’abord à quoi cela ne sert pas
- créer un type de string particulier. Il n’y a rien de tel qu’un type “raw string” en Python. La chaîne résultante est une chaîne ordinaire.
- créer une chaîne destinée aux regex. On utilise particulièrement la notation ‘r’ avec les regex, mais ce n’est pas un type dédié.
‘r’ est juste un modifieur, une sorte de paramètre. En effet, quand vous écrivez 'Salut !\n'
, vous n’écrivez PAS la chaîne “Salut ![LB]“. Vous dites à Python de créer un objet chaîne, de la même manière que vous lui demanderiez une instanciation en faisant MaClasse()
.
'Salut !\n'
est juste une notation, pas la chaîne elle même. Cette notation dit à Python: À partir de cet instant dans le programme, tu vas créer un objet chaîne en mémoire, et voici les paramètres que je te donne pour le créer
. La notation étant différente, on a l’illusion d’écrire la chaîne soi-même, mais en fait ce n’est pas différent d’un appel de fonction.
Quand vous faites 'Salut !\n'
, vous dites plus précisément à Python: Instancie un objet de type string, met les caractères S, a, l, u, t, espace et point d’exclamtion dedans, suivi d’un saut de ligne
. Cette notation, pour se faciliter la vie, permet de décrire “saut de ligne” en écrivant '\n'
. Python analyse donc votre chaîne, cherche toutes les combinaions de charactères spéciaux comme '\n'
, '\t'
, etc, et quand il créer l’objet en mémoire, il ajoute un saut de ligne ou une tabulation, et pas les caractères ‘\’ puis ‘n’ ou ‘t’.
Que se passe-t-il si vous voulez réellement ajouter ‘\’ et ‘n’ ?
Il faut utiliser une autre notation, l’échappement. On utilise un ‘\’ pour dire à Python: créer cet objet en mémoire, mais à cet endroit, ne tient pas compte de la combinaison de caractères spéciaux.
Ceci affiche un saut de ligne: print '\n est le caractère de saut de ligne'
Ceci affiche ‘\’, ‘n’ puis la phrase: print '\\n est le caractère de saut de ligne'
Mais il existe des cas où c’est très fastidieux et illisible. Notamment les expression rationnelles, où les ‘\’ font partie intégrante du système.
Un exemple simple, vous voulez “C:\Program Files” dans une phrase:
Votre regex devra contenir ‘\P’. Saut qu’en regex, ‘\P’ est un symbole special, donc il faut l’échapper, vous aurez donc ‘\\P’. Sauf qu’en Python, il faut échapper les ‘\’ pour qu’il ne soient pas considérés comme caractères spéciaux, vous aurez donc ‘\\\\P’. Sur une regex complexe, ça devient vitre très moche, et très dur à déboguer.
C’est là qu’intervient le modifieur ‘r’, qui précise à Python: quand tu vas créer cette chaîne en mémoire, met ces caractères dedans littéralement et considère qu’il n’y a aucune combinaison de caractères spéciaux
.
En clait r'\n'
sera ‘\’ puis ‘n’. Python ne va tout simplement par parser la chaîne, il va l’utiliser litteralement, d’où le “raw” string.
Il n’y a donc rien de spécial à dans une chaîne créée avec le modifieur ‘r’, c’est une chaîne normale, qui est instanciée sans réfléchir par Python, sans chercher à être malin et comprendre des notations spéciales.
Ca ne veut pas dire qu’on ne peut pas avoir des sauts de ligne dans une chaîne créée avec ‘r’:
>>> print r"""1 + 1 = ... 42""" 1 + 1 42
Ca veut juste dire que les notations spéciales ne seront pas analysées:
>>> print '1 + 1 =\n 42' 1 + 1 = 42 >>> print r'1 + 1 =\n 42' 1 + 1 =\n 42
Il est facile de s’embrouiller les pinceaux à cause du shell Python:
>>> 'test\n' 'test\n' >>> r'test\n' 'test\\n' >>> print 'test\n' test >>> print r'test\n' test\n
Il faut savoir que quand on affiche un objet sans utiliser print
dans le shell, ce dernier essaye de vous afficher une représentation de l’objet de telle sorte qu’il puisse être copié et collé, et recréer le même objet. En revanche, print
va afficher du texte formatté pour être lisible par un humain.
Articles similaires:
Pour tous ceux qui viennent du net en cherchant:
python à quoi sert le “r”
C’est ici !
Question annexe, l’utilisation d’un raw string permet-il un gain en performance ? Merci pour l’article.
Aucune idée. Mais si tu cherches à gagner des performances sur l’initialisation d’une string, Python n’est pas le langage qu’il te faut. A ce stade de besoin (rare) de perf, autant passer au C. Quitte à faire un binding Python par dessus.