Chaînes littérales, édition de code

\(\newcommand{\ds}{\displaystyle}\) \(\newcommand{\Frac}{\ds\frac}\) \(\renewcommand{\r}{\mathbb{ R}}\) \(\newcommand{\C}{\mathbb{ C}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\z}{\mathbb{ Z}}\) \(\newcommand{\Q}{\mathbb{ Q}}\) \(\newcommand{\N}{\mathbb{ N}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\ol}{\overline}\) \(\newcommand{\abs}[1]{\left| \,{#1} \right|}\) \(\newcommand{\pv}{\;;\;}\) \(\newcommand{\ens}[1]{\left\{ {#1} \right\}}\) \(\newcommand{\mens}[1]{\setminus\left\{ {#1} \right\}}\) \(\newcommand{\Par}[1]{\left({#1}\right)}\) \(\newcommand{\pe}[1]{\left\lfloor {#1} \right\rfloor}\) \(\newcommand{\trans}[1]{\,^t\!{#1}}\)

Chaînes littérales, édition de code

Les différents délimiteurs de chaînes littérales

Il existe 4 types de délimiteurs de chaînes littérales :

  • l’apostrophe
  • le guillemet anglais, encore appelé guillemet ou guillemet simple
  • les triples apostrophes
  • les triples guillemets

et voici des exemples d’utilisation :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
s = 'La Lune'

t = "La Terre"

u = """Mars
Jupiter
Saturne"""

v = '''Uranus
Pluton'''

print(s)
print(t)
print(u)
print('--------')
print(v)
17
18
19
20
21
22
23
24
25
La Lune
La Terre
--------
Mars
Jupiter
Saturne
--------
Uranus
Pluton

Un délimiteur quelconque de chaîne littérale sera appelé quote. L’apostrophe et le guillemet anglais seront appelés quotes simples. L’apostrophe et guillemet triples seront appelés quotes triples. Une chaîne littérale encadrée par des quotes simples sera appelée chaîne littérale simple. De même, pour une chaîne triple.

Le délimiteur qui ouvre une chaîne littérale est toujours du même type que le délimiteur qui la ferme. Ainsi la suite de caractère 'hello" ne désigne pas une chaîne littérale valide.

Le choix du type de quotes est, la plupart du temps, indifférent et juste déterminé par la commodité de saisie et la lisibilité de la chaîne littérale. Concernant les chaînes triples, en deux mots, et comme on le voit dans les exemples ci-dessus (lignes 5-7 et 9-10), elles autorisent le saut de ligne, à la différence des chaînes simples.

Une chaîne littérale ouverte par un délimiteur simple mais non fermée entraîne une erreur de syntaxe :

1
2
s = "kiwi
print(s)
3
SyntaxError: EOL while scanning string literal
  • Ligne 3 : EOL abrège End Of Line : le parseur indique qu’il a rencontré la fin de ligne alors qu’il était en train d’examiner une chaîne littérale et donc qu’il attendait le délimiteur de fin de chaîne.

C’est en fait le même problème que de vouloir passer une ligne à l’intérieur d’une chaîne simple :

1
2
3
4
s = 'Uranus
Pluton'

print(s)
5
SyntaxError: EOL while scanning string literal
  • Lignes 1-2 : saut de ligne dans une chaîne littérale simple.

Enfin, ne pas confondre un guillemet et une apostrophe doublée :

s = ''kiwi''
print(s)
    s = ''kiwi''
             ^
SyntaxError: invalid syntax

Un guillemet anglais constitue un seul caractère bien qu’il soit représenté comme si on utilisait deux apostrophes successives.

Chaîne littérale invalide et coloration syntaxique

Dans un éditeur de code, la coloration syntaxique permet en général de discerner qu’un chaîne littérale est invalide. Par exemple, le code suivant

x = "hello" + 'world'
x = "hello' + "world'
x = "hello\" + "world"
print("hello')

se présente ainsi dans une cellule Jupyter Notebook :

../../../_images/wrong_litteral.png

Les chaînes littérales sont normalement colorées en rouge. Les opérateurs en violet, les identificateurs quelconques et les parenthèses en noir. La ligne 1 est valide et sert de modèle. Les autres sont incorrectes :

  • ligne 2 : le signe + devrait être en violet donc l’erreur est avant (apostrophe au lieu de guillemet)
  • ligne 3 : même problème, l’apostrophe a été échappée avec la contre-oblique et donc le mot world se retrouve en noir.
  • ligne 4 : la parenthèse finale est en rouge au lieu d’être en noir car les délimiteurs de chaîne littérale ne correspondent pas.

Quote dans une chaîne littérale

Soit à créer une chaîne littérale S de contenu :

La fable "Le Corbeau et le Renard" de La Fontaine

Noter que cette chaîne contient deux caractères guillemets qui entourent le nom de la fable.

Pour placer cette chaîne en tant que chaîne littérale dans du code Python, il n’est pas possible d’utiliser un délimiteur guillemet. Essayons :

1
2
s = "La fable "Le Corbeau et le Renard" de La Fontaine"
print(s)
3
4
5
    s = "La fable "Le Corbeau et le Renard" de La Fontaine"
                    ^
SyntaxError: invalid syntax
  • Ligne 3 : le parseur Python qui lit la chaîne de la gauche vers la droite n’identifie que la chaîne littérale : La fable car le 2e guillemet marque, pour lui, la fin de la chaîne. La suite (qui commence avec la séquence de caractères Le Corbeau) ne peut être analysée par le parseur car elle ne correspond syntaxiquement à rien.

Pour faire de S une chaîne littérale, il suffit de l’encadrer par un autre délimiteur que le guillemet, par exemple l’apostrophe puisque le caractère apostrophe n’est pas présent dans la chaîne :

1
2
s = 'La fable "Le Corbeau et le Renard" de La Fontaine'
print(s)
3
La fable "Le Corbeau et le Renard" de La Fontaine
  • Ligne 1 : noter que le délimiteur de la chaîne littérale est une apostrophe.

De même, pour créer une chaîne littérale contenant par exemple une apostrophe, comme la chaîne Le loup et l’agneau, il suffit de l’encadrer par un autre délimiteur que l’apostrophe, par exemple des guillemets, en supposant que le caractère guillemet ne soit pas présent dans la chaîne :

s = "Le loup et l'agneau"
print(s)
Le loup et l'agneau

En particulier, on peut définir des chaînes littérales qui représentent l’apostrophe et le guillemet :

APOSTROPHE = "'"
GUILLEMET = '"'
print("apostrophe ->", APOSTROPHE)
print(" guillemet ->", GUILLEMET)
apostrophe -> '
 guillemet -> "

Pour une chaîne contenant à la fois une apostrophe et un guillemet, il y a deux solutions qui seront présentées ultérieurement, l’une utilisant des chaînes triples et l’autre utilisant des échappements de quotes.

Triples quotes

Soit le texte brut suivant :

Mars
Jupiter
Uranus
Neptune

On cherche à construire une chaîne littérale s dont le contenu soit le même que celui affiché ci-dessus, sauts de ligne inclus avec la contrainte de ne pas utiliser de saut de ligne sous la forme \n.

Une chaîne littérale avec simple délimiteur (guillemet ou d’apostrophe) ne peut parvenir au résultat : en effet, les caractères d’une chaîne littérale simple, doivent se trouver sur une même ligne de code (voir cependant Découper une chaîne littérale sur plusieurs lignes).

Justement, un des rôles des chaînes triples est de permettre d’obtenir un caractère saut de ligne en se contentant de taper sur la touche ENTER :

1
2
3
4
5
6
s = """Mars
Jupiter
Uranus
Neptune"""

print(s)
 7
 8
 9
10
Mars
Jupiter
Uranus
Neptune
  • Lignes 1-4 : l’utilisateur a tapé trois fois sur la touche ENTER pour créer la chaîne littérale s. Noter que la chaîne doit commencer et se terminer par des triples quotes, ici des triples guillemets. Les apostrophes de fermeture doivent être écrits sur la même ligne que la fin de la chaîne sinon, vous créez un saut de ligne final dans la chaîne (qui ici n’était pas souhaité).
  • Lignes 7-10 : les sauts de lignes apparaissent à l’affichage.

Il aurait été possible d’obtenir le même effet avec une chaîne encadrée par des apostrophes triples :

s = '''Mars
Jupiter
Uranus
Neptune'''

print(s)

Par ailleurs, il est possible d’utiliser des triples guillemets ou des triples apostrophes en l’absence de saut de ligne :

u = """Mars Jupiter Uranus Neptune"""
print(u)
Mars Jupiter Uranus Neptune

On peut, sauf coïncidence malheureuse, placer à l’intérieur d’une chaîne triple des guillemets et des apostrophes simples :

s = """La Terre ('planète bleue')
Mars ("planète rouge")"""

print(s)
La Terre ('planète bleue')
Mars ("planète rouge")

Choisir une chaîne triple est donc parfois une solution quand l’usage d’une chaîne simple provoque une erreur :

s = """La fable "Le loup et l'agneau" de la Fontaine"""
print(s)
La fable "Le loup et l'agneau" de la Fontaine

Attention, cependant : une fois dans la chaîne littérale, l’interpréteur cherche une succession de trois quotes pour décider de la fin de la chaîne. Si vous êtes malchanceux, vous aurez une erreur :

s = """La Terre ("planète bleue")
Mars  est la "planète rouge""""

print(s)
    Mars dite  "planète rouge""""
                                ^
SyntaxError: EOL while scanning string literal

Ici, il était facile d’y remédier en entourant dès le départ par des triples apostrophes :

s = '''La Terre ("planète bleue")
Mars  est la "planète rouge"'''

print(s)
La Terre ("planète bleue")
Mars  est la "planète rouge"

Usage différencié des délimiteurs de chaînes littérales

Une chaîne littérale peut être entourée de différents délimiteurs. En fonction de quel critère choisira-t-on de définir une chaîne littérale avec tel délimiteur plutôt que tel autre ? Un critère est celui de la meilleure lisibilité ; en particulier, on pourra considérer que la présence de séquence d’échappement nuit à la lisibilité

Délimiteurs simples

Les deux délimiteurs simples sont utilisés souvent de façons équivalentes, bien que l’usage chez les programmeurs semble privilégier l’usage de l’apostrophe sur le guillemet lorsqu’il y a équivalent.

Néanmoins, si une chaîne contient une apostrophe, par exemple l'orange, l’apostrophe ne peut pas servir de délimiteur et on choisira alors des guillemets :

s = "l'orange"
print(s)
l'orange

De même, si une chaîne contient un ou plusieurs guillemets comme La fable "Le Corbeau et le Renard" de La Fontaine on utilisera des apostrophes comme délimiteur.

Délimiteurs triples

Les délimiteurs triples s’utilisent essentiellement lorsque la chaîne littérale contient des sauts de lignes et que pour des raisons de lisibilité et de commodité d’édition, le programmeur ne veut pas faire apparaître les sauts de ligne sous forme de séquences d’échappement (\n) mais sous forme de passage « physique » à ligne. Typiquement :

s = """Mars
Jupiter
Uranus
Neptune"""

print(s)
Mars
Jupiter
Uranus
Neptune

Un usage fréquent des chaînes triples est le placement d’une docstring bien que des doctrings unilignes puissent être entourées de quotes simples (et cela se rencontre dans du code de référence). Voici un exemple inspiré d’une fonction du code-source de Python :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def mean(data):
    """Return the sample arithmetic mean of data.

    >>> mean([1, 2, 3, 4, 4])
    2.8
    """
    return sum(data)/len(data)


print(mean([1, 2, 3, 4, 4]))
11
2.8
  • Lignes 2-6 : une docstring sous forme de chaîne triple.

Une docstring est un détournement astucieux de la notion de chaîne littérale. Attention toutefois à ne pas croire qu’un chaîne triple (ou pas, d’ailleurs) peut remplacer un commentaire, une chaîne triple, seule sur une ou plusieurs ligne, étant une (unique) instruction Python.

Une chaîne triple peut être entourée de guillemets triples ou d’apostrophes triples. En cas d’équivalence d’usage, il semble plus habituel de placer des guillemets triples.

Une chaîne triple est appropriée pour encadrer le contenu d’une chaîne littérale contenant à la fois des apostrophes et des guillemets.

Le fait qu’il y ait deux types de délimiteurs triples permet de placer une chaîne triple comme contenu d’une chaîne littérale :

s = '''La docstring est :

"""Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts."""

extrait du "Zen of Python".'''

print(s)

qui affiche

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
La docstring est :

"""Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts."""

extrait du "Zen of Python".

Chaînes triples et indentation

Les chaînes triples peuvent en apparence ne pas respecter d’indentation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
if True:
    if 42==40+2:
        if 42==40+2:
            if 42==40+2:
                if 42==40+2:
                    if 42==40+2:
                        if 42==40+2 :
                            if 42==40+2:
                                z="""Le Loup et l'agneau

Un agneau se ..."""

print(z)
14
15
16
Le Loup et l'agneau

Un agneau se ...
  • Malgré les apparences, bien que l’affectation soit indentée (ligne 9), ce code respecte l’indentation (ligne 11). Le retrait est obligatoire si on ne veut pas pas introduire une indentation erronée dans la chaîne littérale.

Si on avait conservé l’indentation, on aurait obtenu un affichage sans doute non souhaité :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
if True:
    if 42==40+2:
        if 42==40+2:
            if 42==40+2:
                if 42==40+2:
                    if 42==40+2:
                        if 42==40+2 :
                            if 42==40+2:
                                z="""Le Loup et l'agneau

                                     Un agneau se ..."""

print(z)
14
15
16
Le Loup et l'agneau

                                     Un agneau se ...
  • Ligne 16 : le vers est indenté à tort, à cause de l’indentation incorrecte ligne 11.

C’est une des difficultés que peuvent poser les chaînes triples puisque le code Python est souvent amené à être indenté, par obligation syntaxique

Générer du code Python avec la fonction repr

Comme la fonction repr génère une chaîne littérale Python dont le contenu est une expression Python valide, on peut utiliser facilement la fonction repr pour générer du code Python. Par exemple, on dispose d’une suite de mots dans un fichier :

lundi
mardi
mercredi
jeudi
vendredi
samedi
dimanche

et on veut créer le code d’une liste Python dont tous les éléments soient les chaînes définies par cette liste de mots (par exemple, pour pouvoir replacer la liste dans un code-source Python). Plus précisément, on voudrait générer automatiquement le code Python suivant :

["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"]

à partir de la chaîne lisible dans le texte ci-dessus (noter que les mots doivent apparaître, non pas entourés d’apostrophes, mais de guillemets même si cela ne change pas la valeur de l’objet).

Voici comment la fonction repr permet d’accomplir l’objectif :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
mots="""lundi
mardi
mercredi
jeudi
vendredi
samedi
dimanche"""

code = repr(mots.split())
print(code)
print()

code_final = code.replace("'", '"')

print(code_final)
16
17
18
['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']

["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"]
  • Ligne 18 : objectif atteint puisqu’on a placé les mots dans une liste Python à partir de la chaîne littérale et que les mots sont entourés de guillemets.
  • Lignes 1-7 : on fait un copier-coller du texte depuis le fichier (d’autres méthodes seraient envisageables) dans le fichier-source et on entoure de triples quotes pour en faire une chaîne littérale
  • Ligne 9 : à l’aide de la méthode split, on crée la liste (objet Python) cherchée ; appliquer repr à cet objet transforme l’objet en code littéral Python
  • Ligne 10 et 16 : par défaut, Python affiche les chaînes littérales entourées d’apostrophes. On souhaiterait ici plutôt avoir des guillemets.
  • Ligne 13 : disposant d’une chaîne (ligne 9), on peut la modifier avec des fonctions Python pour la transformer ; ici, on change les apostrophes en guillemets.

Découper une chaîne littérale sur plusieurs lignes

Soit le programme suivant contenant une longue chaîne littérale :

s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
print(len(s))
62
  • Noter que 62 = 26 + 26 + 10 où 26 désigne le nombre de lettres de l’alphabet et 10 le nombre de chiffres décimaux.

Pour des raisons de lisibilité, on peut vouloir faire apparaître la chaîne s coupée en différents tronçons, par exemple, on voudrait faire apparaître dans la chaîne littérale les regroupements suivants :

abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789

Solution adéquate

Pour découper s en tronçons, il suffit de couper la chaîne sur plusieurs lignes logiques, séparées par le symbole de contre-oblique \ :

s = "abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
0123456789"
print(len(s))
62

En effet, la séquence de caractères \ENTER (c’est-à-dire la contre-oblique suivie d’un appui sur la touche ENTER) réalise une continuation de ligne (cela inhibe le saut de ligne). Cela permet de découper une longue ligne (« logique » comme on dit) sur plusieurs lignes (« physiques »).

Noter cependant que le formatage suivant, qui cherche à aligner les débuts de lignes, modifie la chaîne littérale :

1
2
3
4
s = "abcdefghijklmnopqrstuvwxyz\
     ABCDEFGHIJKLMNOPQRSTUVWXYZ\
     0123456789"
print(len(s))
5
72
  • Ligne 5 : la longueur de la chaîne est 72 alors que la chaîne initiale est de longueur 62 ; cela est dû aux espaces ajoutés avant ABCD... (ligne 2) ainsi que 0123... (ligne 3).

Noter qu’il serait possible d’obtenir un effet d’alignement :

s = "\
abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
0123456789"
print(len(s))
62

On aurait pu essayer d’utiliser une chaîne triple. Mais la représentation suivante n’est cependant pas fidèle :

s = """abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789"""
print(len(s))
64
  • la longueur de s n’est pas la même que celle de la chaîne initiale (64 au lieu de 62) car des sauts de lignes ont été introduits dans la chaîne triple.

Lien vers la documentation officielle : Explicit line joining

Découper du code Python sur plusieurs lignes

Le placement d’un saut de ligne dans du code Python est très strict. Une instruction uniligne ne peut pas a priori être placée sur deux lignes. Par exemple, soit à évaluer la longue addition ci-dessous :

8 + 11 + 17 + 14 + 10 + 11 + 6 + 4 + 1 + 7 + 7 + 8 + 2 + 6 + 5 + 20 + 20 + 2

en plaçant la somme sur deux lignes de code Python :

s = 8 + 11 + 17 + 14 + 10 + 11 + 6 + 4 + 1 +
7 + 7 + 8 + 2 + 6 + 5 + 20 + 20 + 2

print(s)

Ce code poduit une erreur :

    s = 8 + 11 + 17 + 14 + 10 + 11 + 6 + 4 + 1 +
                                                ^
SyntaxError: invalid syntax

et cette erreur est due au passage à la ligne.

Il existe deux façons de pallier cette limitation :

  • placer une contre-oblique à l’endroit où on veut couper la ligne,
  • entourer la liste entre des délimiteurs appariés, comme des parenthèses.

voir les paragraphes dédiés pour le détail.

Enjambement de lignes avec un appariement

On peut contourner l’impossibilité de passer à la ligne à l’intérieur d’une expression en plaçant l’expression à l’intérieur d’une paire de délimiteurs comme des parenthèses, des crochets, des accolades, selon les possibilités qu’offre la situation. Par exemple, pour présenter une longue addition, pourra faire comme suit :

1
2
3
4
s = (58 + 20 + 33 + 86 + 87 + 25 +
     74 + 70 + 54 + 16 + 58 + 40 +
     49 + 54 + 92 + 13 + 51 + 51)
print(s)
5
931
  • Lignes 1-3 : l’expression a été placée entre parenthèses et elle peut être ensuite découpée en autant de lignes que l’on souhaite. On peut aussi placer des blancs comme on le souhaite à l’intérieur des parenthèses. Les 3 lignes sont dites lignes physiques et elles correspondent à une seule ligne dite logique.

Cette possibilité est applicable dans de nombreuses situations et permet d’améliorer la lisibilité du code. Elle permet par exemple, de placer des listes littérales sur plusieurs lignes :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
for L in [
            [5, 8, 0, 9, 1, 0, 6, 4],
            [0, 0, 0, 4, 0, 3, 0],
            [5, 8, 1, 6, 4],
            [-5, -8],
            [0, -5, -8],
            [-3, 0, -5, -8],
            [0, 5, -8],
            [42],
            [-42]]:
    print(L, '->', sum(L))
  • lignes 2-10 : on a placé une grosse liste de listes que l’on peut indenter comme on souhaite.

Le placement d’un code entre délimiteur permet aussi l’insertion de commentaires en fin de ligne physique :

L = [
    65, 31, 9, 81,      # impairs
    32,  82, 46, 12     # pairs
    ]

Enjambement de lignes avec une contre-oblique

On peut contourner l’impossibilité de passer à la ligne dans une expression en plaçant une contre-oblique juste à l’endroit où on fait le saut de ligne dans l’expression. Exemple appliqué au calcul d’une longue addition :

1
2
3
s = 58 + 20 + 33 + 86 + 87 + 25 + 74 + 70 + 54 + \
    16 + 58 + 40 + 49 + 54 + 92 + 13 + 51 + 51
print(s)
4
931
  • Ligne 1 : on a placé la contre-oblique à la fin de la ligne, juste avant d’effectuer le saut de ligne. Il ne doit y avoir aucun caractère entre la contre-oblique et l’endroit où on appuie sur la touche ENTRÉE pour sauter la ligne.
  • Ligne 1-2 : ces deux lignes constituent, pour l’interpréteur Python, une seule ligne (logique). Chacune des deux lignes est dite physique.
  • Ligne 2 : on peut indenter, à des fins de meilleure lisibilité, pour aligner les termes de la somme car cela signifie juste ajouter des espaces entre le signe + de la fin de la ligne 1 et le nombre 16 de la ligne 2.

Il est même possible de placer plusieurs contre-obliques pour la même espression :

s = 58 + 20 + 33 + 86 + 87 + 25 +\
    74 + 70 + 54 + 16 + 58 + 40 +\
    49 + 54 + 92 + 13 + 51 + 51
print(s)
931

Puisqu’on place une contre-oblique avant de taper sur la touche ENTRÉE, cette possibilité peut se voir comme un échappement du saut de ligne et j’écrirai parfois \ENTRÉE.

Il n’y a que très peu de limitation à cette règle ; en voici une néanmoins : on ne peut pas couper un nombre littéral, ni couper un identificateur. Exemple :

# Code interdit
pi = 3.141592653589\
    7932384626433

# Code interdit
maLongue\
Variable = 42

Il est par ailleurs recommandé de limiter l’usage de ce type de coupure de ligne.

Fusion de chaînes littérales adjacentes

Des chaînes littérales placées côte-à-côte et sur une même ligne (logique) dans du code-source sont traitées comme si elles formaient une seule chaîne littérale :

s = "Rose""Kiwi""Prune"
print(s)
RoseKiwiPrune

Les chaînes peuvent même être séparées par des espaces et avoir des séparateurs différents :

s = "Rose" 'Kiwi'  """Prune
Fraise
Poire"""

print(s)
RoseKiwiPrune
Fraise
Poire

Lien vers la documentation officielle : String literal concatenation

Édition lisible de chaînes littérales

En utilisant les possibilités de fusion de chaînes littérales adjacentes ainsi que le découpage de lignes logiques, il est possible de formater dans le code-source une chaîne littérale, longue ou structurée, de façon lisible. Soit le programme suivant contenant une longue chaîne littérale :

s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
print(len(s))
62

On peut rendre plus lisible la chaîne littérale ci-dessus par le code suivant :

1
2
3
4
s = "abcdefghijklmnopqrstuvwxyz"\
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\
    "0123456789"
print(len(s))
5
62
  • Lignes 1-3 : il s’agit d’une seule ligne logique mais répartie sur trois lignes physiques grâce à l’échappement \ENTER. On notera qu’aucun caractère du contenu de la chaîne s n’est le caractère saut de ligne.
  • lignes 2 et 3 : les deux chaînes littérales sont précédées d’espaces pour permettre l’alignement vertical des 3 chaînes. Ces espaces ne sont pas incorporés dans la chaîne, ils servent juste à la présentation.

Comme aucun caractère du contenu de la chaîne s n’est le caractère saut de ligne, la chaîne ne pouvait être ré-écrites avec des quotes triples.

On peut même encore simplifier le code : le code d’une expression peut être coupé sur plusieurs lignes si l’expression est entourée d’une paire de délimiteurs comme des parenthèses. D’où la ré-écriture suivante :

s = ("abcdefghijklmnopqrstuvwxyz" # minuscules
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # majuscules
     "0123456789")                # chiffres

print(len(s))
62

Noter qu’il a même été possible de rajouter des commentaires en fin de chaque ligne.

La problématique de l’échappement

Imaginons une chaîne littérale représentant un texte contenant des sauts de lignes, par exemple :

Lundi
Mardi
Mercredi

Pour qu’une telle chaîne existe en Python, une chaîne de caractères doit pouvoir exprimer avec un marqueur spécifique qu’elle contient, à tel endroit, un saut de ligne. Or, le saut de ligne est un caractère non-imprimable. Il faut donc trouver un mécanisme pour pouvoir représenter le caractère saut de ligne à partir d’autres caractères sans que ces caractères soient interprétés à la lettre. Ce mécanisme s’appelle l’échappement.

L”échappement en Python est effectué avec le caractère \, dit contre-oblique. Ainsi, pour représenter un saut de ligne, en anglais newline, on utilise le caractère n précédé d’une contre-oblique, ce qui donne le caractère \n :

1
2
s = "Lundi\nMardi\nMercredi"
print(s)
3
4
5
Lundi
Mardi
Mercredi
  • Ligne 1 : quand la chaîne est parcourue de la gauche vers la droite, la combinaison du caractère \ suivi du caractère n forme un unique caractère, interprétée comme un saut de ligne. La chaîne s contient trois fois cette combinaison. Noter que la coloration syntaxique du code a placé en gras la séquence d’échappement.
  • Lignes 3-5 : les trois mots sont bien séparés par des sauts de ligne.

Caractère unique

Ainsi, la présence d’une contre-oblique devant certains caractères a pour effet de modifier le sens habituel (littéral) du caractère. Dans ce contexte, on dit que la contre-oblique est un caractère d’échappement et la combinaison contre-oblique + caractère formant le caractère interprété est appelée la séquence d’échappement. Par exemple, les deux caractères assemblés \n forment une séquence d’échappement.

Une séquence d’échappement s’écrit avec deux caractères (rarement plus) dans le code-source mais représente un seul caractère Python. Pour le vérifier, il suffit d’examiner la longueur d’une chaîne contenant une séquence d’échappement :

1
2
s = "\n"
print(len(s))
3
1
  • Ligne 1 : s est littéralement constitué de deux caractères : la contre-oblique et le caractère n
  • Ligne 3 : s représente UN seul caractère (ici, le saut de ligne).

Représenter une quote par une séquence d’échappement

Comme l’apostrophe et le guillemet sont à la fois des caractères et des délimiteurs de chaînes, il est possible d’échapper ces caractères avec une contre-oblique. Ainsi, le caractère \' est la séquence d’échappement représentant une apostrophe, le caractère \" est la séquence d’échappement représentant un guillemet anglais.

Voici un exemple d’utilisation :

1
2
3
4
s = "La fable \"Le loup et l\'agneau\" de la Fontaine"
t = 'La fable \"Le loup et l\'agneau\" de la Fontaine'
print(s)
print(t)
5
6
La fable "Le loup et l'agneau" de la Fontaine
La fable "Le loup et l'agneau" de la Fontaine
  • Lignes 1 et 2 : les chaînes s et t ont même valeur ; elles sont seulement encadrées par des délimiteurs différents.
  • Lignes 1 et 2 : les deux guillemets autour du titre Le loup et l’agneau sont échappés en \"
  • Lignes 1 et 2 : l’apostrophe qui précède le mot agneau est échappée en \'.

Séquences d’échappement usuelles

Voici les séquences d’échappement les plus usuelles :

Nom Séquence d” échappement
Saut de ligne \n
Tabulation \t
Contre-oblique \\
Ignorance d’un saut de ligne \ENTER
Apostrophe \'
Guillemet \"

Ces séquences ne s’appliquent qu’à des chaînes littérales sauf \ENTER qui s’applique aussi à du code Python, cf. Enjambement de lignes avec une contre-oblique.

Échappement du caractère contre-oblique

Le caractère noté \ est appelé contre-oblique (en anglais antislash). C’est un caractère de type ponctuation. On s’intéresse à ce caractère, non pas en tant que caractère d’échappement dans une chaîne littérale, mais en tant que vrai caractère pouvant être utilisé dans une chaîne au même titre qu’une lettre.

Soit à créer une chaîne littérale de contenu :

C:\Users\Pascal
  • La chaîne contient 15 caractères (1+5+6 = 12 lettres, le caractère deux-points et deux caractères contre-oblique)

Si on cherche à afficher en tant que chaîne littérale :

path = "C:\Users\Pascal"
print(path)
  File "code.py", line 1
    path = "C:\users\Pascal"
          ^
SyntaxError: (unicode error) 'unicodeescape' codec can't decode
                    bytes in position 2-3: truncated \uXXXX escape

on aurait un message d’erreur, cf. la sortie ci-dessus. Explication : la séquence de caractères \U (dans \Users) au lieu d’être interprétée comme deux caractères (d’abord \ puis U) serait interprétée comme une séquence d’échappement.

Le caractère \ ne peut être représenté tel quel dans une chaîne littérale. Pour obtenir un caractère contre-oblique, il suffit d’écrire \\, ce qui est assez logique puisque la contre-oblique sert à réaliser un échappement.

Cette fois l’affichage est réalisé correctement :

path = "C:\\Users\\Pascal"
print(path)
C:\Users\Pascal

En particulier, la chaîne littérale ayant pour unique caractère une contre-oblique est "\\" :

print("\\")
\

Ces questions sont particulièrement importantes à comprendre si vous êtes amené à utiliser des expressions régulières.

Contre-oblique littérale : bonne pratique

Ce paragraphe traite d’une question très marginale.

Une contre-oblique dans une chaîne littérale n’est pas forcément le début d’une séquence d’échappement. C’est le cas si le caractère qui suit la contre-oblique ne définit pas une séquence d’échappement répertoriée :

s = "C:\Documents and Settings"
print(s)
C:\Documents and Settings
  • A l’affichage (ligne 3), on lit bien une contre-oblique suivie de la lettre D, cela veut dire que dans la chaîne littérale (ligne 1), les deux caractères \D ne forment pas une séquence d’échappement mais deux caractères autonomes.

Si on est malchanceux, et si on n’a pas connaissance de la liste de toutes les séquences d’échappement, la chaîne construite peut ne pas correspondre à ce qu’on souhaite.

Or, il est possible de ne pas produire de séquence d’échappement si on double la contre-oblique. Donc on écrira plutôt (ligne 4) :

s = "C:\Documents and Settings"
print(s)
s = "C:\\Documents and Settings"
print(s)
C:\Documents and Settings
C:\Documents and Settings

L’intérêt de doubler une contre-oblique littérale est que si, par exemple, dans une version ultérieure de Python, \D devient une séquence d’échappement, la version \D n’aurait plus la même interprétation tandis que le code utilisant \\D resterait valide. Bien qu’il paraît improbable qu’une telle séquence soit introduite, tant cela risquerait de casser de code, le risque n’est pas exclu que dans un future version de Python, cet usage entraîne une erreur de syntaxe.

Le caractère tabulation

La tabulation horizontale, sert à faire des alignements verticaux de texte, comme dans le tableau suivant de nombres en colonnes :

45  119     43      54
490 23      72      39
1   23      256     44

La question est de savoir comment placer des tabulations horizontales dans une chaîne littérale. Pour cela, on marque la tabulation dans la chaîne à l’aide de la séquence d’échappement \t :

print("45\t119\t43\t54\n490\t23\t72\t39\n1\t23\t256\t44")
45      119     43      54
490     23      72      39
1       23      256     44

Noter qu’en réalité, il n’est pas nécessaire d’utiliser une séquence d’échappement pour placer des tabulations dans une chaîne littérale :

1
2
3
4
5
t="""45     119     43      54
490 23      72      39
1   23      256     44"""

print(repr(t))
'45\t119\t43\t54\n490\t23\t72\t39\n1\t23\t256\t44'

et la sortie montre bien que des tabulations ont été saisies au clavier pour séparer les nombres.

Il ne faut pas confondre cette possibilité d’utiliser des « tabulations-clavier » dans une chaîne littérale Python et les restrictions à utiliser ces mêmes tabulations dans du code Python hors de chaînes littérales.

Les chaînes littérales ne s’appliquent qu’à du code-source

Les multiples techniques permettant de construire des chaînes littérale ne doivent pas faire croire que le contenu d’une chaîne littérale est « complexe » voire qu’il y aurait un type chaîne littérale. Une fois une chaîne référencée dans une variable, à l’exécution du programme, sa provenance éventuelle d’une chaîne littérale n’a aucune particularité.

Par exemple, soit la chaîne de caractères suivante

La chaîne de caractères : 'J'ai entendu : " on joue au "plus\moins""'

Cette chaîne est assez compliquée à construire en tant que chaîne littérale, cela pourrait par exemple être :

s = 'La chaîne de caractères : \'J\'ai entendu : " on joue au "plus\\moins""\''
print(s)
La chaîne de caractères : 'J'ai entendu : " on joue au "plus\moins""'

Toutefois, on peut très bien capturer cette chaîne sans aucun effort si elle n’est pas une chaîne littérale, par exemple si cette chaîne est récupérée par la fonction input :

1
2
3
S = input("Entrez du texte :\n")
print("Voici votre texte :\n")
print(S)
4
5
6
7
8
Entrez du texte :
La chaîne de caractères : 'J'ai entendu : " on joue au "plus\moins""'
Voici votre texte :

La chaîne de caractères : 'J'ai entendu : " on joue au "plus\moins""'
  • Lignes 1 et 4-5 : la chaîne est capturée par la fonction input, elle est produite par un utilisateur
  • Lignes 3 et 8 : la chaîne est restituée telle quelle.

Identification du contenu d’une chaîne littérale

Une chaîne pré-existe à sa représentation en Python et un écart important peut séparer son contenu de sa représentation en chaîne littérale. Par exemple, soit la chaîne suivante placée sur deux lignes :

C:\toto
"OK"

Une représentation possible de ce texte sous forme de chaîne littérale Python pourrait être :

S = "C:\\toto\n\"OK\""

Il est bien clair qu’il n’est pas évident de déchiffrer le contenu de S et d’y reconnaître le texte ci-dessus.

Une méthode simple pour identifier le contenu d’une chaîne présentée par une chaîne littérale consiste à :

  • afficher la chaîne avec la fonction print
  • lire la suite de caractères produits.

Illustration :

S = "C:\\toto\n\"OK\""
print(S)
C:\toto
"OK"

Il apparaît alors que S contient 12 caractères (7 lettres, 1 saut de ligne et 4 caractères de ponctuation). Noter que pourtant, la représentation de S en tant que chaîne littérale Python est très différente et nécessite, non pas 12, mais 16 caractères. Cette méthode est presque infaillible (elle pourrait échouer par exemple si la chaîne contenait un caractère \b mais c’est anecdotique).

Le contenu d’une chaîne est la succession de caractères qu’on lit dans une console quand on affiche la chaîne avec la fonction print (en supposant que la chaîne soit formée de caractères imprimables).

Une autre méthode, très simple, pour discerner les caractères successifs du contenu d’une chaîne (littérale ou pas d’ailleurs), est de transformer la chaîne en liste :

1
2
3
4
5
6
7
S = "C:\\toto\n\"OK\""
print(S)
print()

L= list(S)
print(len(L))
print(L)
 8
 9
10
11
12
C:\toto
"OK"

12
['C', ':', '\\', 't', 'o', 't', 'o', '\n', '"', 'O', 'K', '"']
  • Lignes 2 et 8-9 : on lit bien la chaîne S.
  • Ligne 11 : on retrouve que la chaîne représentée en Python par S contient 12 caractères.
  • Lignes 5 et 12 : la liste de chaque caractère de S

Contre-oblique en dernier caractère d’une chaîne littérale

Le contenu de ce paragraphe est d’importance secondaire.

Une chaîne littérale dont le contenu se termine par une unique contre-oblique est invalide car cette contre-oblique serait vue comme un caractère d’échappement du délimiteur de sortie de chaîne littérale :

1
2
3
s = "hello\"

print(s)
4
5
6
    s = "hello\"
               ^
SyntaxError: EOL while scanning string literal
  • Ligne 1 : s est une chaîne de caractères terminée par une et une seule contre-oblique.
  • Ligne 6 : s est forcément une chaîne invalide car le guillemet n’est plus vu comme un délimiteur mais comme un caractère de la chaîne (à cause de l’échappement créé par la contre-oblique) en sorte que s ne possède plus de délimiteur final.

Nombre pair de contre-obliques

Si le contenu d’une chaîne littérale doit se terminer par des contre-obliques, elles doivent figurer en nombre pair dans la chaîne littérale, par exemple :

print("hello\\\\\\")
hello\\\

chaque paire représentant en fait une unique contre-oblique en sorte que le délimiteur de chaîne final ne subit aucun échappement.

Lien vers la documentation officielle : raw literal cannot end in a single backslash

L’usage de chaînes brutes peut largement simplifier le code.

Analyse lexicale d’une contre-oblique

Le contenu de cette unité est anecdotique et a surtout pour object de tester sa compréhension des mécanismes d’échappement.

Soit une chaîne littérale contenant une contre-oblique comme les chaînes suivantes :

s = "oui\non"
t = "non\oui"

Voici par quel principe le caractère contre-oblique est identifié par le parseur Python quand il scanne la chaîne avant l’exécution.

Un point essentiel est le suivant : le parseur lit la chaîne littérale de la gauche vers la droite. En particulier, avant de parser la chaîne, il ne sait pas combien de caractères la chaîne représentée contient.

Quand il rencontre un caractère contre-oblique, avant de l’interpréter, il regarde le caractère immédiatement après cette contre-oblique dans la chaîne, disons qu’il s’appelle c. Essentiellement, deux cas se présentent :

  • si la contre-oblique et c forment une séquence d’échappement reconnue, elle est interprétée comme une séquence d’échappement, par exemple si c est le caractère n, la séquence \ suivi de n est interprétée comme un caractère saut de ligne ;
  • sinon, la contre-oblique est interprétée littéralement comme une contre-oblique.

Comparer :

s = "oui\non"
t = "non\oui"
u = "oui\\non"
v = "non\\oui"

print(s)
print("-----------")

print(t)
print("-----------")

print(u)
print("-----------")

print(v)
print("-----------")
oui
on
-----------
non\oui
-----------
oui\non
-----------
non\oui
-----------
  • Pour s, u et v, la séquence formée de la première contre-oblique et du caractère qui suit immédiatement est une séquence d’échappement : \n pour s et \\ pour u et v.
  • Les séquences d’échappement sont interprétées comme telles : un saut de ligne pour s et une vraie contre-oblique pour u et v.
  • Pour t, la séquence formée de la première contre-oblique et du caractère qui suit immédiatement est \o qui n’est pas une séquence d’échappement. Donc, cette séquence est interprétée comme les deux caractères littéraux : une contre-oblique suivie de la lettre o.

Caractères \b et \r

Le combinaison de caractères \b effectue un déplacement arrière du curseur d’écriture et peut donc avoir un effet d’effacement, un peu comme appuyer sur la touche du clavier Retour Arrière :

1
print("Hello worL\bd!")
2
Hello word!
  • Ligne 2 : observez que la lettre L a été écrasée.

La lettre b du caractère fait référence au nom de backspace (retour arrière en anglais). On rencontre peu en pratique le recours à ce caractère. Il ne s’agit pas véritablement d’un caractère d’effacement, mais plutôt de retour-arrière du curseur, car il n’y a pas forcément d’effacement :

1
print("Hello worLd\b\b")
2
Hello worLd

Le caractère \r (carriage return autrement dit retour chariot) à pour effet de reprendre l’affichage au début de la même ligne et a donc un effet d’écrasement :

print("Hello\nDear\rWorld")
Hello
World

Comme on peut le voir dans la sortie, la présence du caractère \r a fait reculer le curseur d’écriture des caractères jusqu’au début de la ligne où le curseur se trouvait, donc juste après le caractère saut de ligne \n, ce qui a eu pour effet d”écraser la chaîne Dear.

Ce caractère est parfois utilisé pour placer des affichages successifs sur une même ligne :

1
2
3
4
5
import time

for i in range(10):
    print(f"Décompte : {i+1}", flush=True, end='\r')
    time.sleep(1)

qui affiche

../../../_images/decompte.gif

où on voit que les affichages restent toujours sur la même ligne.

La fonction repr appliquée à une chaîne

Si X est une chaîne alors repr(X) est aussi une chaîne mais toujours différente de X car repr(X) est une chaîne dont le contenu est une chaîne littérale et donc le premier caractère de repr(X) est toujours un délimiteur de chaîne littérale :

1
2
3
4
5
6
7
8
X = "bonjour"
Y = repr(X)

print(X[0])
print(X)
print()
print(Y[0])
print(Y)
 9
10
11
12
13
b
bonjour

'
'bonjour'
  • Lignes 4 et 9 : X est une chaîne littérale mais le premier caractère de X n’est pas un délimiteur de chaîne mais la lettre b.
  • Lignes 7 et 12 : le premier caractère de Y est un délimiteur (ici une apostrophe), le dernier aussi d’ailleurs.

Pour représenter le délimiteur de chaîne litérale, il semble que l’interpréteur Python, s’il a le choix, préfère l’apostrophe au guillement.

Construire une chaîne littérale avec repr

La fonction repr permet aussi de définir une chaîne littérale de contenu une chaîne donnée X.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
APOS = "'"
GUIL = '"'
SDL = '\n'

X = APOS *3 + GUIL + SDL+ APOS + SDL + APOS * 3
Y= repr(X)

print("--------- La chaîne X : -----------")
print(X)
print("-- Chaîne X littérale valant X : --")
print(Y)
12
13
14
15
16
17
--------- La chaîne X : -----------
'''"
'
'''
-- Chaîne X littérale valant X : --
'\'\'\'"\n\'\n\'\'\''
  • Ligne 5 : X est une chaîne bâtie à partir de caractères « spéciaux »
  • Ligne 6 : Y est une chaîne qui est un équivalent sous forme d’une chaîne littérale Python de contenu X

Si on copie-colle la chaîne affichée ligne 17, sans rien ajouter (même pas de quotes extérieures) dans du code Python, on obtient une chaîne littérale qui à même valeur que X :

1
2
3
4
5
6
7
APOS = "'"
GUIL = '"'
SDL = '\n'

X = APOS *3 + GUIL + SDL+ APOS + SDL + APOS * 3
Y= '\'\'\'"\n\'\n\'\'\''
print(X == Y)
8
True
  • Ligne 6 : on a copié-collé textuellement l’affichage produit par print(repr(X)) obtenu au code précédent
  • Ligne 8 : Python nous dit que les objets sont égaux : c’est le point à comprendre concernant la fonction repr.

Transformer une chaîne en une chaîne littérale

Le contenu de ce paragraphe est peu utile en pratique et d’importance secondaire.

Présentons le problème à travers un exemple. Soit la chaîne s de contenu suivant :

"oui"\non'

Cette chaîne ne doit pas être vue comme une chaîne littérale. Cette chaîne comporte 10 caractères. Le guillemet initial n’est pas à interpréter comme un délimiteur de chaîne littérale Python, ce guillemet est simplement le premier caractère de la chaîne s. Aucune séquence de la chaîne s n’est à interpréter comme une séquence d’échappement, par exemple la séquence \n NE représente PAS le caractère saut de ligne mais bien DEUX caractères consécutifs de s : la contre-oblique suivie du caractère n.

On cherche à créer une chaîne littérale Python S dont le contenu soit celui de s. Cela pourrait se faire facilement avec des chaînes brutes mais il n’en sera pas question pour l’instant. Ainsi, une fois S déterminée, l’extrait de code

print(S[0])
print(S[5], S[6])

devra afficher

"
\ n

Il existe au moins deux méthodes pour résoudre ce problème :

  • génération de S, caractère par caractère, par analyse gauche-droite de s
  • génération de S, après placement de s dans un fichier texte et application de la fonction repr

Chaîne vers chaîne littérale par analyse gauche-droite

Voyons la première méthode. Le principe de construction de S, assez laborieux, est le suivant :

  • on parcourt la chaîne s de la gauche vers la droite, caractère par caractère.
  • si le caractère examiné c n’est pas une contre-oblique ni un guillemet, ce caractère produira le même caractère c dans S.
  • si le caractère c est une contre-oblique dans s, ce caractère produira les deux caractères \\ dans S
  • si le caractère c est un guillemet dans s, ce caractère produira les deux caractères \" dans S
  • si le caractère c est une apostrophe dans s, ce caractère produira les deux caractères \' dans S.

Avec cette méthode, on obtient la chaîne littérale S suivante :

# "oui"\non'

S = "\"oui\"\\non\'"
print(S)
"oui"\non'

Chaîne vers chaîne littérale en utilisant la fonction repr

Voyons la 2e méthode, elle est un peu laborieuse aussi :

  • on construit une chaîne t (non littérale) dont le contenu soit s
  • on applique la fonction built-in repr à t ce qui renvoie la chaîne cherchée S

Pour construire t, on place textuellement s (par copier-coller) dans un fichier texte. Ensuite, pour récupérer le texte sous forme de chaîne Python t, on ouvre le fichier texte avec open et on capture le texte avec la méthode read.

repr(t) renvoie une représentation de t sous forme de code-source exécutable, autrement dit, la chaîne littérale cherchée S est repr(t). Pour obtenir la chaîne littérale cherchée, il suffit donc d’afficher avec la fonction print l’objet repr(t) et de faire un copier-coller dans le code-source de ce qui s’affiche à l’écran.

Voici un code complet. On suppose que la chaîne s a été placée dans le fichier chaine.txt :

"oui"\non'

Le code Python est alors :

1
2
3
4
fichier = open("chaine.txt")
t = fichier.read()
z=repr(t)
print(z)
5
'"oui"\\non\''

Vérifions par comparaison visuelle que la chaîne littérale affichée ci-dessus a bien pour contenu la chaîne s initiale :

1
2
s = '"oui"\\non\''
print(s)
3
"oui"\non'
  • Ligne 1 : s est obtenue par copier-coller de l’affichage ligne 5 du précédent code Python.
  • La sortie montre que le contenu de s est bien la chaîne initiale S.

Cette méthode s’appliquerait encore si la chaîne S s’étendait sur plusieurs lignes.

Chaînes brutes

Notion de chaîne brute

Une chaîne brute (en anglais, raw string) est une chaîne littérale préfixée par r ou par R et qui retire à la contre-oblique sa propriété de caractère d’échappement :

1
2
3
4
5
6
s = "oui\non"
print(s)
print()

r = r"oui\non"
print(r)
 7
 8
 9
10
oui
on

oui\non
  • Ligne 1 : chaîne littérale habituelle ; la séquence \n est une séquence d’échappement et est interprétée comme le caractère saut de ligne
  • Ligne 5 : une chaîne brute reconnaissable à ce que la chaîne littérale est précédée du préfixe r.
  • Ligne 10 : lorsque la chaîne est brute, la suite de deux caractères \n n’est pas interprétée comme une séquence d’échappement mais est interprétée littéralement, comme deux caractères : la contre-oblique suivie du caractère n, d’où l’absence de saut de ligne.

Pourquoi les chaînes brutes ?

Les chaînes littérales (non brutes) ne sont pas adaptées à la saisie de texte contenant de nombreuses occurrences du caractère d’échappement \. Par exemple soit une chaîne littérale s dont le contenu C est

1
une apostrophe : \t\'\nun slash : \t\t\\\nun saut de ligne : \t\\n

autrement dit s est une chaîne littérale telle que print(s) affiche le contenu ci-dessus. Ainsi, il ne faut pas considérer ici la sous-chaîne \t de C comme une séquence d’échappement mais bien comme deux caractères successifs de C.

Le code ci-dessous fournit une chaîne littérale s dont le contenu est C :

s = 'une apostrophe : \\t\\\'\\nun slash : \\t\\t\\\\\\nun saut de ligne : \\t\\\\n'
print(s)
une apostrophe : \t\'\nun slash : \t\t\\\nun saut de ligne : \t\\n

On voit que chaque contre-oblique a dû être doublée et que l’apostrophe a dû être remplacée par sa séquence d’échappement. C’est pour éviter ce type de complication qu’existent les chaînes brutes.

Usage des chaînes brutes

Une chaîne brute sert essentiellement à faciliter la construction de chaînes littérales représentant des chaînes de caractères contenant une contre-oblique comme caractère de la chaîne. Par exemple, on utilise des chaînes brutes pour

  • saisir des chaînes littérales à utiliser avec des expressions régulières, c’est un usage très répandu, commode et presque obligatoire ;
  • produire du code LaTeX dont les commandes commencent par une contre-oblique, par exemple \begin{document} ;
  • saisir des chemins de fichiers sous Windows, comme C:\User\monDoc ;
  • sans doute bien d’autres situations.

Les délimiteurs d’une chaîne brute

Une chaîne brute peut avoir pour délimiteur n’importe quel délimiteur de chaîne littérale, y compris des triples quotes :

s = r"""oui\non
oui\non
oui\non"""
print(s)
oui\non
oui\non
oui\non

Construire une chaîne littérale complexe en passant par une chaîne brute

Soit la chaîne de caractères C suivante :

une apostrophe : \t\'\nun slash : \t\t\\\nun saut de ligne : \t\\n

Cherchons une chaîne littérale L qui représente C. Pour cela, il suffit de transformer C en chaîne littérale brute :

r = r'une apostrophe : \t\'\nun slash : \t\t\\\nun saut de ligne : \t\\n'
print(r)
une apostrophe : \t\'\nun slash : \t\t\\\nun saut de ligne : \t\\n

On observe que la création de la chaîne littérale r s’est faite sans effort : il a suffi d’entourer le contenu C de la chaîne par une paire d’apostrophes, le premier quote étant précédé du marqueur r de chaîne brute (cette solution n’est pas universelle, il aurait pu y avoir un conflit de quotes par exemple).