Interpolation de chaînes en Python : exploration des outils disponibles
L'interpolation de chaînes vous permet de créer des chaînes en insérant des objets à des endroits spécifiques dans un modèle de chaîne cible. Python dispose de plusieurs outils pour l'interpolation de chaînes, notamment les f-strings, la méthode str.format()
et l'opérateur modulo (%
). Le module string
de Python fournit également la classe Template
, que vous pouvez utiliser pour l'interpolation de chaînes.
Dans ce didacticiel, vous allez :
- Apprenez à utiliser les f-strings pour une interpolation empressée de chaînes.
- Effectuez une interpolation de chaîne paresseuse à l'aide de la méthode
str.format()
- Apprenez les bases de l'utilisation de l'opérateur modulo (
%
) pour l'interpolation de chaînes. - Décidez si vous souhaitez utiliser des f-strings ou la méthode
str.format()
pour l'interpolation - Créez des modèles pour l'interpolation de chaînes avec
string.Template
Pour tirer le meilleur parti de ce didacticiel, vous devez être familier avec les chaînes Python, qui sont représentées par la classe str
.
Interpolation de chaînes en Python
Parfois, lorsque vous travaillez avec des chaînes, vous créez des chaînes en utilisant plusieurs valeurs de chaîne différentes. Au départ, vous pouvez utiliser l'opérateur plus (+
) pour concaténer des chaînes en Python. Cependant, cette approche aboutit à un code avec de nombreux guillemets et avantages :
>>> name = "Pythonista"
>>> day = "Friday" # Of course 😃
>>> "Hello, " + name + "! Today is " + day + "."
'Hello, Pythonista! Today is Friday.'
Dans cet exemple, vous créez une chaîne en utilisant du texte et quelques variables contenant des valeurs de chaîne. Les nombreux signes plus rendent le code difficile à lire et à écrire. Python doit avoir une méthode meilleure et plus propre.
Remarque : Pour en savoir plus sur la concaténation de chaînes en Python, consultez le didacticiel Concaténation efficace de chaînes en Python.
L'opérateur modulo (%
) est venu améliorer un peu la syntaxe :
>>> "Hello, %s! Today is %s." % (name, day)
'Hello, Pythonista! Today is Friday.'
Dans cet exemple, vous utilisez l'opérateur modulo pour insérer les variables name
et day
dans les littéraux de chaîne. Le processus de création de chaînes en y insérant d’autres chaînes, comme vous l’avez fait ici, est connu sous le nom d’interpolation de chaîne.
Remarque : Le formatage avec l'opérateur modulo est inspiré du formatage printf()
utilisé en C et dans de nombreux autres langages de programmation.
La combinaison de caractères %s
est connue sous le nom de spécificateur de conversion. Ils fonctionnent comme des champs de remplacement. L'opérateur %
marque le début du spécificateur, tandis que la lettre s
est le type de conversion et indique à l'opérateur que vous souhaitez convertir l'entrée. objet dans une chaîne. Vous en apprendrez plus sur les spécificateurs de conversion dans la section sur l'opérateur modulo.
Remarque : Dans ce didacticiel, vous découvrirez deux types différents d'interpolation de chaîne :
- Interpolation empressée
- Interpolation paresseuse
En interpolation hâtive, Python insère les valeurs dans la chaîne au moment de l'exécution, au même endroit où vous définissez la chaîne. En interpolation paresseuse, Python retarde l'insertion jusqu'à ce que la chaîne soit réellement nécessaire. Dans ce dernier cas, vous créez des modèles de chaînes à un moment donné de votre code et remplissez le modèle avec des valeurs à un autre moment.
Mais l’histoire ne s’arrête pas à l’opérateur modulo. Plus tard, Python a introduit la méthode str.format()
:
>>> "Hello, {}! Today is {}.".format(name, day)
'Hello, Pythonista! Today is Friday.'
La méthode interpole ses arguments dans la chaîne cible en utilisant des champs de remplacement limités par des accolades. Même si cette méthode peut produire du code difficile à lire, elle représente une avancée significative par rapport à l'opérateur modulo : elle prend en charge le mini-langage de formatage de chaîne.
Remarque : Le formatage des chaînes est un sujet fondamental en Python, et parfois, les gens pensent que le formatage et l'interpolation sont identiques. Cependant, ce n’est pas le cas. Dans ce didacticiel, vous n’en apprendrez plus que sur l’interpolation. Pour en savoir plus sur le formatage des chaînes et le mini-langage de formatage, consultez le didacticiel Python Format Mini-Language for Tidy Strings.
Python continue d'évoluer et chaque nouvelle version apporte de nouvelles fonctionnalités intéressantes. Python 3.6 a introduit les chaînes littérales formatées, ou f-strings en abrégé :
>>> f"Hello, {name}! Today is {day}."
'Hello, Pythonista! Today is Friday.'
Les chaînes F offrent un moyen plus lisible et plus propre de créer des chaînes incluant d'autres chaînes. Pour créer une f-string, vous devez la préfixer avec un f
ou un F
. Encore une fois, des accolades délimitent les champs de remplacement.
Remarque : Pour en savoir plus sur les f-strings, consultez le didacticiel Python F-String for String Interpolation and Formatting.
Les chaînes F sont probablement l'outil d'interpolation le plus populaire de nos jours en Python. Ils sont lisibles, rapides à écrire et efficaces. Vous commencerez donc par les f-strings et comment les utiliser pour créer de nouvelles chaînes à l’aide de l’interpolation.
Utilisation de littéraux de chaîne F pour créer des chaînes
Pour la plupart des cas d'utilisation d'interpolation, les f-strings sont probablement le meilleur choix si vous utilisez Python 3.6 ou supérieur. Leur syntaxe est lisible et concise. De plus, ils fonctionneront plus rapidement que les autres outils.
Un cas d’utilisation dans lequel les f-strings ne sont pas la solution est celui où vous devez effectuer une interpolation paresseuse. En d’autres termes, lorsque vous devez créer un modèle de chaîne et insérer les composants ultérieurement en fonction de l’exécution du code. Dans ce cas, Python prend l'option paresseuse et retarde le calcul de la valeur renvoyée par une expression jusqu'à ce que cette valeur soit nécessaire.
Une autre considération à garder à l’esprit est la sécurité. Étant donné que les f-strings sont évaluées au moment de l’exécution, elles pourraient potentiellement exposer votre application à des attaques par injection de code si vous ne nettoyez pas soigneusement les entrées des utilisateurs avant l’interpolation.
Dans les sections suivantes, vous apprendrez à utiliser les f-strings pour une interpolation empressée de chaînes en Python.
Interpolation de valeurs dans les chaînes F
En utilisant les f-strings, vous pouvez interpoler des variables et des expressions directement dans vos chaînes. Ensuite, lorsque Python exécute la f-string, le contenu de la variable ou le résultat de l'expression sera interpolé dans le littéral de la f-string pour construire la chaîne finale :
>>> x = 5
>>> y = 10
>>> f"The sum of {x} and {y} is {x + y}."
'The sum of 5 and 10 is 15.'
Dans cet exemple, vous avez deux variables, x
et y
. Ensuite, vous créez un littéral de chaîne f avec trois champs de remplacement. Les deux premiers champs contiennent les variables et le troisième champ contient une expression.
Il est important de noter que Python évalue les f-strings au moment de l'exécution. Ainsi, dans cet exemple, x
, y
et x + y
sont évalués et interpolés dans la chaîne littérale lorsque Python exécute la ligne de code contenant la chaîne f.
Vous pouvez intégrer presque toutes les expressions Python dans une chaîne f, telles que des expressions arithmétiques, de comparaison et booléennes. Vous pouvez également utiliser des fonctions et des appels de méthodes, et même des compréhensions ou d'autres expressions plus complexes :
>>> import math
>>> radius = 16
>>> f"The area of your circle is {math.pi * radius ** 2}"
'The area of your circle is 804.247719318987'
>>> name = "Pythonista"
>>> site = "real python"
>>> f"Hello, {name.upper()}! Welcome to {site.title()}!"
'Hello, PYTHONISTA! Welcome to Real Python!'
>>> f"{[2**n for n in range(3, 9)]}"
'[8, 16, 32, 64, 128, 256]'
Dans la première f-string, vous intégrez une expression mathématique dans le champ de remplacement. Dans le deuxième exemple, vous utilisez les méthodes de chaîne .upper()
et .title()
dans les champs de remplacement. Python évalue l'expression et appelle la méthode pour vous. Ensuite, il insère les résultats dans le littéral de chaîne f résultant. Dans le dernier exemple, vous créez une f-string qui intègre une compréhension de liste. La compréhension crée une nouvelle liste de puissances de 2
.
Remarque : Les f-strings de Python convertissent les valeurs interpolées en chaînes par défaut :
>>> f"The number is {42}"
'The number is 42'
>>> f"Pi {3.14}"
'Pi 3.14'
Dans ces exemples, vous interpolez des valeurs numériques dans votre f-string. Python les convertit en objets chaîne lors de l'interpolation.
Les chaînes F antérieures à Python 3.12 présentent quelques limitations dont vous devez tenir compte lorsque vous travaillez avec elles. Dans les champs de remplacement, vous ne pouvez pas :
- Réutiliser les guillemets ou les délimiteurs de chaîne
- Intégrez des barres obliques inverses, ce qui signifie que vous ne pouvez pas utiliser de séquences d'échappement.
- Ajouter des commentaires en ligne
- Chaînes F Nest au-delà des variantes de cotation disponibles
Le PEP 536 répertorie toutes ces limitations. Pour les voir en action, consultez la section F-Strings Had Some Limitations Before Python 3.12 dans le didacticiel Python 3.12 Preview.
Auto-documentation de la valeur interpolée
Avec les f-strings, vous pouvez utiliser une fonctionnalité connue sous le nom d'expressions auto-documentées qui ajoute un signe égal après la variable ou l'expression interpolée. Cette fonctionnalité peut vous aider à déboguer votre code. Pour un débogage rapide, la plupart des gens utilisent la fonction intégrée print()
pour vérifier la valeur d'une variable ou le résultat d'une expression :
>>> value = "Suspicious value"
>>> print(f"{value = }")
variable = 'Suspicious value'
>>> f"{2 + 3 = }"
'2 + 3 = 5'
Vous pouvez utiliser une variable ou une expression suivie d'un signe égal (=
) dans une f-string pour créer une expression auto-documentée. Lorsque Python exécute la f-string, il crée une chaîne de type expression contenant la variable ou l'expression, le signe égal et le résultat actuel.
Dans ces exemples, les espaces autour du signe égal ne sont pas obligatoires, mais ils rendent la sortie plus lisible.
La fonctionnalité d'expressions auto-documentées ajoute de la lisibilité à votre processus d'interpolation de chaînes et peut être un excellent outil pour un débogage rapide avec print()
.
Utilisation de différentes représentations de chaînes dans les chaînes F
Les chaînes F vous permettent d'utiliser deux indicateurs ayant une signification particulière dans le processus d'interpolation. Ces indicateurs concernent la façon dont Python gère la représentation sous forme de chaîne d'un objet. Voici les drapeaux et leur signification :
!s
Interpole la représentation sous forme de chaîne à l'aide de
.__str__()
!r
Interpole la représentation sous forme de chaîne à l'aide de
.__repr__()
Idéalement, la méthode spéciale .__str__()
devrait fournir une représentation sous forme de chaîne conviviale d'un objet. Python revient à appeler cette méthode lorsque vous utilisez la fonction str()
. Pendant ce temps, la méthode .__repr__()
renvoie une représentation conviviale pour les développeurs, que vous obtenez lorsque vous utilisez la fonction repr()
.
Remarque : L'indicateur !s
est le comportement par défaut dans les f-strings, vous aurez donc rarement besoin de l'utiliser explicitement.
Pour illustrer le fonctionnement de ces indicateurs, considérons l'exemple de classe suivant :
class Article:
def __init__(self, title, author, pub_date):
self.title = title
self.author = author
self.pub_date = pub_date
def __str__(self):
return (
f"Article: {self.title}\n"
f"Author: {self.author}\n"
f"Published: {self.pub_date}\n"
)
def __repr__(self):
return (
f"{type(self).__name__}("
f"title={self.title!r}, "
f"author={self.author!r}, "
f"pub_date={self.pub_date!r})"
)
Cette classe Article
a trois attributs d'instance .title
, .author
et .pub_date
. La méthode .__str__()
renvoie une chaîne contenant les informations de l'article dans un format convivial. Ce message s'adresse aux utilisateurs finaux plutôt qu'aux développeurs.
Remarque : Pour approfondir les méthodes .__str__()
et .__repr__()
, consultez Quand devriez-vous utiliser. .__repr__()
contre .__str__()
en Python ?
La méthode .__repr__()
renvoie une chaîne qui est une représentation conviviale de l'objet pour les développeurs. En bref, la représentation indique au développeur comment l'instance actuelle a été créée. Idéalement, le développeur devrait pouvoir copier cette représentation sous forme de chaîne et créer un objet équivalent.
Votre classe est maintenant prête pour les indicateurs !s
et !r
:
>>> from article import Article
>>> article = Article(
... title="String Interpolation in Python: Exploring Available Tools",
... author="Real Python",
... pub_date="2024-06-03",
... )
>>> print(f"{article!s}")
Article: String Interpolation in Python: Exploring Available Tools
Author: Real Python
Published: 2024-06-03
>>> print(f"{article!r}")
Article(
title='String Interpolation in Python: Exploring Available Tools',
author='Real Python',
pub_date='2024-06-03'
)
Dans la première f-string, vous utilisez la balise !s
pour interpoler la représentation sous forme de chaîne renvoyée par .__str__()
. Dans la deuxième f-string, vous utilisez l'indicateur !r
pour interpoler la représentation sous forme de chaîne conviviale pour les développeurs de votre objet. Notez que, dans ce dernier cas, l’objet chaîne résultant représente un code Python valide que vous pouvez évaluer.
Création de chaînes avec la méthode str.format()
Si vous avez besoin d'interpoler des valeurs dans des chaînes paresseusement, alors la méthode str.format()
est faite pour vous. Cette méthode est un outil polyvalent pour l'interpolation de chaînes en Python. Il fournit une syntaxe lisible et permet une interpolation à la fois hâtive et paresseuse.
Remarque : N'oubliez pas que l'interpolation hâtive est effectuée au moment de l'exécution et que l'interpolation paresseuse se produit lorsque vous créez un modèle de chaîne et reportez l'interpolation des valeurs à une date ultérieure.
Dans les sections suivantes, vous apprendrez à utiliser la méthode .format()
pour une interpolation paresseuse car, dans la plupart des cas, vous utiliserez des chaînes f pour une interpolation hâtive.
Utiliser des arguments positionnels et nommés
Pour interpoler des objets dans une chaîne à l'aide de la méthode .format()
, vous pouvez utiliser trois approches différentes. Vous pouvez utiliser :
- Champs de remplacement vides,
{}
- Champs de remplacement avec des indices de base zéro,
{0} ... {n}
- Champs de remplacement avec des arguments nommés,
{arg_1} ... {arg_n}
Pour illustrer le fonctionnement de ces options, disons que vous devez automatiser le processus de génération d'e-mails pour les clients qui achètent des produits auprès de votre entreprise. Vous pouvez créer un modèle d'e-mail puis interpoler les données client de manière dynamique :
>>> template = """
... Dear {},
...
... Thank you for your recent purchase of {}.
...
... Remember, our support team is always here to assist you.
...
... Best regards,
... {}
... """
>>> print(template.format("Emily", "MacBook Pro 16-inch", "John"))
Dear Emily,
Thank you for your recent purchase of MacBook Pro 16-inch.
Remember, our support team is always here to assist you.
Best regards,
John
Dans cet exemple, vous créez un modèle d'e-mail avec trois champs de remplacement vides. La méthode .format()
insère les valeurs transmises dans le champ approprié en utilisant leur position relative. Si vous souhaitez avoir un peu plus de contrôle sur la façon dont les valeurs sont interpolées, vous pouvez utiliser des indices entiers :
>>> template = """
... Dear {0},
...
... Thank you for your recent purchase of {1}.
...
... Remember, our support team is always here to assist you.
...
... Best regards,
... {2}
... """
>>> print(template.format("Linda", "Samsung Galaxy S22", "Jane"))
Dear Linda,
Thank you for your recent purchase of Samsung Galaxy S22.
Remember, our support team is always here to assist you.
Best regards,
Jane
Dans cet exemple, le résultat est similaire. Cependant, vous êtes maintenant certain que le premier argument, "Linda"
, ira à l'index 0
, le deuxième argument, "Samsung Galaxy S22"
ira à l'index 1
, et ainsi de suite. Cette façon de gérer les arguments peut être utile lorsque l’ordre d’origine des arguments n’est pas le même que l’ordre dans la chaîne finale :
>>> template = """
... Dear {1},
...
... Thank you for your recent purchase of {0}.
...
... Remember, our support team is always here to assist you.
...
... Best regards,
... {2}
... """
>>> purchase = ("Samsung Galaxy S22", "Linda", "Jane")
>>> print(template.format(*purchase))
Dear Linda,
Thank you for your recent purchase of Samsung Galaxy S22.
Remember, our support team is always here to assist you.
Best regards,
Jane
Ici, l'ordre des éléments dans le tuple purchase
ne correspond pas à l'ordre naturel dans le modèle. Ainsi, vous déplacez les indices selon le nouvel ordre et obtenez le résultat souhaité.
Remarque : Vous pouvez également répéter les indices des arguments dans un modèle de chaîne. Prenons l'exemple de jouet suivant :
>>> prefix = "re"
>>> template = "{0}-create and {0}start"
>>> template.format(prefix)
're-create and restart'
Dans cet exemple, vous utilisez la variable prefix
comme argument de .format()
. En insérant l'index 0
deux fois dans le modèle, vous obtenez également un prefix
inséré deux fois.
Même si les options ci-dessus fonctionnent correctement, elles ne sont pas entièrement lisibles. Heureusement, il existe une meilleure solution. Vous pouvez utiliser des arguments de mots-clés avec .format()
. Voici comment procéder :
>>> template = """
... Dear {customer},
...
... Thank you for your recent purchase of {product}.
...
... Remember, our support team is always here to assist you.
...
... Best regards,
... {employee}
... """
>>> print(
... template.format(
... customer="Bob",
... product="Canon EOS R5",
... employee="Kate"
... )
... )
Dear Bob,
Thank you for your recent purchase of Canon EOS R5.
Remember, our support team is always here to assist you.
Best regards,
Kate
Dans cette mise à jour, vous avez utilisé des noms explicites dans les champs de remplacement. Ces noms correspondent aux arguments de mots clés que vous avez utilisés lors de l'appel de .format()
. Votre code semble maintenant beaucoup plus lisible.
Enfin, il est également possible d'utiliser des dictionnaires pour alimenter la méthode .format()
. Supposons que vous récupériez vos données à partir d'un fichier CSV qui ressemble à ceci :
product,customer,employee
MacBook Pro 16-inch,Emily,John
Samsung Galaxy S22,Linda,Jane
Canon EOS R5,Bob,Kate
Vous pouvez utiliser le module csv
de la bibliothèque standard pour traiter ce fichier et charger son contenu afin de pouvoir créer des emails pour chaque vente. Le csv.DictReader
est un bon outil pour cette tâche. Ce lecteur vous permet de lire chaque ligne d'un fichier CSV dans un dictionnaire. Les clés seront les en-têtes de fichiers et les valeurs seront les valeurs de chaque ligne.
Voici le code que vous pouvez utiliser pour effectuer le travail :
import csv
template = """
Dear {customer},
Thank you for your recent purchase of {product}.
Remember, our support team is always here to assist you.
Best regards,
{employee}
"""
def display_emails(template, path):
with open(path) as file:
for customer in csv.DictReader(file):
print(template.format(**customer))
display_emails(template, "sales.csv")
Dans ce code, vous importez d'abord csv
depuis la bibliothèque standard. Ensuite, vous disposez du modèle d’e-mail habituel avec des noms dans les champs de remplacement. Les noms correspondent aux en-têtes du fichier CSV.
Ensuite, vous avez la fonction display_emails()
. Cette fonction prend deux arguments : le modèle d'e-mail et le chemin d'accès au fichier CSV. À l'intérieur de la fonction, vous ouvrez le fichier d'entrée en lecture à l'aide d'une instruction with
.
La boucle for
parcourt les lignes du fichier à l'aide de la classe DictReader
. Enfin, vous utilisez la méthode .format()
pour interpoler les valeurs de la ligne actuelle dans le modèle d'e-mail. Dans cet exemple, vous utilisez l'opérateur de décompression du dictionnaire (**
) pour fournir les arguments à .format()
.
Allez-y et exécutez ce script à partir de votre ligne de commande pour vérifier le résultat.
Il existe un autre comportement intéressant de .format()
lorsque vous l'utilisez avec des dictionnaires. Voici un exemple rapide de jouet :
>>> numbers = {"one": 1, "two": 2, "three": 3}
>>> "{one}-{two}".format(**numbers)
'1-2'
>>> "{one}-{two}-{three}".format(**numbers)
'1-2-3'
>>> "{one}-{two}-{three}-{four}".format(**numbers)
Traceback (most recent call last):
...
KeyError: 'four'
Lorsque les clés du dictionnaire d'entrée correspondent aux arguments nommés dans la chaîne, l'interpolation fonctionne même si vous avez des clés inutilisées. Lorsque les clés ne correspondent pas aux arguments nommés, vous obtenez une exception KeyError
.
Utilisation de différentes représentations de chaîne avec .format()
Comme avec les f-strings, vous pouvez également utiliser les indicateurs !s
et !r
avec .format()
pour insérer des objets dans vos chaînes en utilisant différentes représentations de chaînes. En réutilisant la classe Article
de la section Utilisation de différentes représentations de chaînes dans les chaînes F, voici deux exemples qui montrent comment fonctionnent les indicateurs :
>>> from article import Article
>>> article = Article(
... title="String Interpolation in Python: Exploring Available Tools",
... author="Real Python",
... pub_date="2024-06-03",
... )
>>> print("{article!s}".format(article=article))
Article: String Interpolation in Python: Exploring Available Tools
Author: Real Python
Published: 2024-06-03
>>> print("{article!r}".format(article=article))
Article(
title='String Interpolation in Python: Exploring Available Tools',
author='Real Python',
pub_date='2024-06-03'
)
Encore une fois, l'indicateur !s
vous permet d'utiliser la représentation sous forme de chaîne conviviale de l'objet en question. En revanche, l'indicateur !r
vous permet d'utiliser la représentation conviviale pour les développeurs. Vous déciderez quel indicateur utiliser dans votre code en tenant compte du public cible de votre code.
Utilisation de l'opérateur Modulo (%
) pour l'interpolation
L'utilisation de l'opérateur modulo (%
) pour l'interpolation de chaînes est largement obsolète dans Python moderne. Cependant, cet outil fonctionne toujours et vous trouverez probablement du code existant qui l'utilise. Il est donc bon de savoir comment cela fonctionne.
Remarque : Dans Python moderne, vous verrez souvent des chaînes F utilisées et vous vous retrouverez à les utiliser pour l'interpolation de chaînes. En effet, les f-strings sont lisibles, propres et rapides. Il existe cependant de meilleures solutions pour certains cas d’utilisation. Parfois, vous devez effectuer une interpolation paresseuse, auquel cas l'outil recommandé est la méthode .format()
. Ainsi, vous finirez probablement par ignorer complètement l'opérateur modulo dans l'interpolation de chaîne.
L'opérateur modulo (%
) est le plus ancien outil permettant d'effectuer une interpolation de chaînes en Python. Même si vous pouvez utiliser cet opérateur pour une interpolation de chaîne à la fois rapide et paresseuse, la syntaxe pourrait être plus lisible et plus propre.
Vous devez insérer des spécificateurs de conversion dans vos chaînes, puis utiliser l'opérateur modulo pour interpoler les valeurs souhaitées :
>>> x = 5
>>> y = 10
>>> "The sum of %d and %d is %d." % (x, y, x + y)
'The sum of 5 and 10 is 15.'
Une combinaison de caractères commençant par le signe de pourcentage (%
) est appelée spécificateur de conversion. Dans cet exemple, vous avez utilisé le spécificateur %d
, ce qui signifie que vous souhaitez convertir une valeur décimale entière signée en chaîne. Les spécificateurs de conversion fonctionnent comme des champs de remplacement pour l'opérateur modulo.
Remarque : L'opérateur modulo est le seul outil d'interpolation qui vous permet d'interpoler des valeurs dans des objets octets
:
>>> name = b"Pythonista"
>>> b"Hello, %b!" % name
b'Hello, Pythonista!'
Vous ne pouvez pas effectuer ce type d'interpolation en utilisant des f-strings car la syntaxe fb""
ou bf""
n'est pas valide. La méthode .format()
ne permet pas ce type d'interpolation car les objets bytes
n'ont pas cette méthode.
Pour effectuer une interpolation paresseuse, vous pouvez procéder comme suit :
>>> template = "The sum of %d and %d is %d."
>>> template % (x, y, x + y)
'The sum of 5 and 10 is 15.'
Dans cet exemple, vous créez une chaîne de modèle avec les champs de remplacement requis. Ensuite, vous utilisez l'opérateur modulo pour interpoler les valeurs dans le modèle plus tard dans votre code. Cette pratique vous permet de réutiliser la chaîne du modèle dans plusieurs parties différentes de votre code.
Remarque : Python fournit de nombreux autres spécificateurs de format pour l'opérateur modulo. Pour une liste complète, consultez la section Formatage de chaîne de style printf dans la documentation de Python.
Pour en savoir plus sur d'autres utilisations de l'opérateur modulo de Python (%
), consultez le didacticiel Python Modulo en pratique : comment utiliser l'opérateur %.
Ensuite, vous disposez de l’opérateur modulo et d’un tuple de valeurs ou d’expressions. L'opérateur interpolera chaque valeur de ce tuple dans le spécificateur approprié en utilisant leur position.
Interpolation d'une ou plusieurs valeurs
Dans la section précédente, vous avez vu un exemple dans lequel vous avez interpolé plusieurs valeurs ou expressions dans une chaîne à l'aide de l'opérateur modulo. Si vous devez insérer une seule valeur, vous pouvez ignorer le tuple ou utiliser un tuple à un seul élément :
>>> "Hello, %s!" % "Pythonista"
'Hello, Pythonista!'
>>> "Hello, %s!" % ("Pythonista",)
'Hello, Pythonista!'
La première syntaxe est un peu plus propre que la seconde syntaxe. Cependant, pour des raisons de cohérence dans votre code, vous souhaiterez peut-être utiliser la deuxième syntaxe.
Maintenant, que se passe-t-il lorsque vous devez interpoler un objet tuple ? Voici un exemple :
>>> "Interpolating a tuple: %s" % (1, 2, 3)
Traceback (most recent call last):
File "<input>", line 1, in <module>
"Interpolating a tuple: %s" % (1, 2, 3)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
TypeError: not all arguments converted during string formatting
Dans cet exemple, Python interprète le tuple comme trois valeurs différentes et vous obtenez une erreur car la chaîne n'a qu'un seul champ de remplacement. Pour contourner ce problème, vous devez utiliser un tuple à élément unique :
>>> "Interpolating a tuple: %s" % ((1, 2, 3),)
'Interpolating a tuple: (1, 2, 3)'
Maintenant, l'interpolation fonctionne correctement et vous vous retrouvez avec le tuple inséré dans la chaîne. Il est important de noter que vous devez utiliser des tuples si vous avez l'intention d'introduire plusieurs valeurs dans l'opérateur modulo :
>>> "Hello, %s! Today is %s." % [name, day]
Traceback (most recent call last):
File "<input>", line 1, in <module>
"Hello, %s! Today is %s." % [name, day]
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
TypeError: not enough arguments for format string
>>> "The sum of %d and %d is %d." % [x, y, x + y]
Traceback (most recent call last):
File "<input>", line 1, in <module>
"The sum of %d and %d is %d." % [x, y, x + y]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
TypeError: %d format: a real number is required, not list
Si vous utilisez un objet list
ou un autre itérable, alors Python l'interprétera comme un objet unique et l'interpolation échouera avec une exception TypeError
.
Utilisation de champs de remplacement nommés
Dans la section précédente, vous avez appris que vous devez utiliser un tuple pour fournir plusieurs arguments à l'opérateur modulo pour l'interpolation de chaîne. De cette façon, l'opérateur insère les valeurs du tuple dans la chaîne cible en fonction de leur position, mais ce n'est pas très lisible.
Heureusement, il existe une meilleure solution. Vous pouvez également utiliser des dictionnaires et des champs de remplacement nommés :
>>> jane = {"name": "Jane", "job": "Python Dev"}
>>> "My name is %(name)s. I'm a %(job)s." % jane
"My name is Jane. I'm a Python Dev."
Dans cet exemple, l'opérateur modulo insère chaque valeur à l'aide de la clé correspondante, ce qui est bien plus lisible et intuitif. Pour créer les champs de remplacement nommés, vous devez insérer le nom entre parenthèses entre le signe %
et le spécificateur de format.
Utilisation de différentes représentations de chaînes
Vous pouvez également utiliser les différentes représentations sous forme de chaîne d'objets avec l'opérateur modulo pour l'interpolation de chaîne. Vous avez déjà appris que le spécificateur de conversion %s
convertit l'objet en chaînes. Pour ce faire, le spécificateur utilise la représentation conviviale de la méthode spéciale .__str__()
.
Pour utiliser la représentation sous forme de chaîne conviviale pour les développeurs fournie dans .__repr__()
, vous pouvez utiliser le spécificateur de conversion %r
.
Pour illustrer comment procéder, vous pouvez à nouveau utiliser la classe Article
:
>>> from article import Article
>>> article = Article(
... title="String Interpolation in Python: Exploring Available Tools",
... author="Real Python",
... pub_date="2024-06-03",
... )
>>> print("%s" % article)
Article: String Interpolation in Python: Exploring Available Tools
Author: Real Python
Published: 2024-06-03
>>> print("%r" % article)
Article(
title='String Interpolation in Python: Exploring Available Tools',
author='Real Python',
pub_date='2024-06-03'
)
Le comportement résultant est le même qu'avec les f-strings et la méthode .format()
. Encore une fois, le choix de la représentation sous forme de chaîne à utiliser dépendra du public cible de votre code.
Utilisation de F-Strings vs .format()
vs %
Jusqu’à présent, vous avez découvert trois outils Python différents que vous pouvez utiliser pour l’interpolation de chaînes. Une question qui peut se poser est la suivante : quel outil devriez-vous utiliser ? Comme pour beaucoup de choses, la réponse est : cela dépend.
Si vous souhaitez une syntaxe lisible et de bonnes performances en interpolation de chaînes et que vous effectuez uniquement une interpolation hâtive, alors les f-strings sont faites pour vous. Si vous avez besoin d'un outil pour effectuer une interpolation de chaîne paresseuse, alors la méthode .format()
est la solution.
En revanche, l'opérateur modulo (%
) est un outil démodé qui n'est pas couramment utilisé dans Python moderne. On pourrait dire que cet outil est presque mort. Cependant, vous pouvez le trouver dans le code Python existant, il est donc bon d'apprendre comment cela fonctionne.
Le tableau suivant compare les trois outils en utilisant plusieurs critères de comparaison :
Feature | F-strings | .format() |
% |
---|---|---|---|
Readability | High | Medium | Low |
Supports lazy evaluation | ⛔️ | ✅ | ✅ |
Supports dictionary unpacking | ⛔️ | ✅ | ✅ |
Supports the format mini-language | ✅ | ✅ | ⛔️ |
Les cordes F sont clairement les gagnantes en termes de lisibilité. Cependant, ils ne vous permettent pas d’effectuer une interpolation paresseuse. Il n'existe aucun moyen d'utiliser une f-string pour créer un modèle de chaîne réutilisable que vous pourrez interpoler ultérieurement dans votre code.
De plus, vous ne pouvez pas utiliser un dictionnaire pour fournir les valeurs d’entrée en une seule fois. Cela ne signifie pas que vous ne pouvez pas interpoler les clés du dictionnaire dans une f-string :
>>> numbers = {"one": 1, "two": 2, "three": 3}
>>> f"{numbers['one']}-{numbers['two']}-{numbers['three']}"
'1-2-3'
Pour interpoler les clés du dictionnaire dans une f-string, vous devez insérer la clé dans le champ de remplacement souhaité. Cela peut rendre votre f-string encombrée et difficile à lire et à écrire. Il est préférable d'utiliser la méthode .format()
dans de tels cas :
>>> "{one}-{two}-{three}".format(**numbers)
'1-2-3'
>>> "{one}-{two}".format(**numbers)
'1-2'
Ce code est beaucoup plus lisible et plus rapide à écrire que la version f-string. Comme avantage supplémentaire, le nombre de clés dans le dictionnaire d'entrée ne doit pas nécessairement correspondre au nombre de champs de remplacement dans la chaîne du modèle, ce qui rend le code plus flexible et générique.
Enfin, les f-strings et la méthode .format()
prennent en charge le mini-langage de formatage de chaîne Python, qui vous permet de formater joliment les valeurs interpolées. Pour un exemple rapide, voici comment formater la constante π en utilisant quatre décimales :
>>> import math
>>> math.pi
3.141592653589793
>>> f"{math.pi:.4f}"
'3.1416'
>>> "{pi:.4f}".format(pi=math.pi)
'3.1416'
Le formatage des valeurs interpolées à l'aide du mini-langage de formatage dépasse le cadre de ce didacticiel. Si vous souhaitez approfondir ce sujet, consultez le didacticiel Python Format Mini-Language for Tidy Strings.
Création de modèles avec la classe Template
Python dispose d'un autre outil pour effectuer une interpolation de chaînes. Dans le module string
, vous trouverez la classe Template
. Comme son nom l'indique, cette classe vous permet de créer des modèles de chaînes que vous pouvez utiliser pour une interpolation paresseuse.
Vous trouverez deux différences principales entre le Template
et les outils d'interpolation de chaînes standard. Avec Template
, le type des valeurs interpolées n'est pas pris en compte. Les valeurs sont automatiquement converties en chaînes puis insérées dans le modèle.
De plus, Template
ne prend pas en charge le formatage des chaînes. En revanche, les outils standards ont l’avantage de supporter le mini-langage de formatage de chaînes, ce qui vous aidera à affiner vos chaînes.
Remarque : La classe Template
est conçue pour vous aider à créer des modèles complexes basés sur des chaînes que vous pouvez gérer de manière conviviale. Cependant, dans la plupart des situations, la méthode .format()
fournit une solution plus complète.
Pour créer une chaîne de modèle avec Template
, vous avez besoin d'une chaîne Python standard avec des espaces réservés intégrés. Ces espaces réservés se composent de deux parties :
- Le signe dollar (
$
) - Un identifiant Python valide
Les identifiants valides sont ceux que vous pouvez utiliser comme noms de variables en Python. Ils combinent des lettres majuscules et minuscules, des traits de soulignement (_
) et des chiffres. Les identifiants ne peuvent pas commencer par des chiffres ni correspondre à un mot-clé Python. Par exemple, $name
, $age
, $Tag
, $class_
et $item_1
sont tous des espaces réservés valides.
Une fois que vous avez créé la chaîne avec les espaces réservés appropriés, vous devez :
- Importez le
Template
depuis le modulestring
- Instanciez le
Template
en utilisant la chaîne du modèle comme argument - Effectuez la substitution avec l'une des deux méthodes pertinentes
Voici un exemple rapide de la façon dont vous pouvez utiliser Template
dans votre code :
>>> from string import Template
>>> template = Template("Hello, $name! Today is $day.")
>>> template.substitute(name="John", day="Friday")
'Hello, John! Today is Friday.'
Dans cet exemple, vous utilisez une chaîne de modèle avec deux espaces réservés, $name
et $day
, comme argument de Template
. Une fois que vous avez instancié la classe, vous pouvez appeler .substitute()
pour interpoler les valeurs. Notez que les noms des arguments que vous transmettez à .substitute()
doivent correspondre aux identifiants utilisés dans les espaces réservés de votre chaîne de modèle.
Dans les sections suivantes, vous en apprendrez davantage sur la création de chaînes de modèles avec la classe Template
.
Création de chaînes de modèles
Pour créer des chaînes de modèle valides que vous pouvez transmettre à la classe Template
, vous devez prendre en compte quelques règles de base. Voici comment la PEP 292 décrit ces règles :
$$
est une évasion ; il est remplacé par un seul$
$identifier
nomme un espace réservé de substitution correspondant à une clé de mappage de « identifier ». Par défaut, « identifier » doit épeler un identifiant Python tel que défini dans [2]. Le premier caractère non identifiant après le caractère$
termine cette spécification d'espace réservé.$ {identifier
est équivalent à$identifier
. Il est requis lorsque des caractères d'identification valides suivent l'espace réservé mais n'en font pas partie, par ex."$ {noun}ification"
. (Source)
Pour commencer, vous commencerez par un exemple montrant comment échapper le signe dollar ($
), qui est nécessaire pour exprimer les valeurs monétaires, par exemple :
>>> from string import Template
>>> Template("$$$amount").substitute(amount="1,000.00")
'$1,000.00'
Dans ce modèle de chaîne, les deux premiers signes dollar échappent au signe dollar requis et le dernier signe dollar définit l'espace réservé.
La deuxième règle stipule que chaque espace réservé nécessite un caractère $
suivi d'un identifiant Python valide. Voici un exemple :
>>> Template("$greeting, $who!").substitute(greeting="Hello", who="World")
'Hello, World!'
Dans cet exemple, vous formez les espaces réservés à l'aide d'identifiants Python valides, greeting
et who
. Comme l'indique la deuxième règle, le premier caractère non identifiant termine l'espace réservé, c'est donc le cas de la virgule après $greeting
et du point d'exclamation après $who
.
La troisième règle s'applique aux situations où vous devez remplacer un mot dans une chaîne et où les caractères qui suivent l'identifiant sont valides pour créer des identifiants. Dans cette situation, Python ne saura pas où se termine l’identifiant.
Par exemple, disons que vous avez besoin d'un modèle qui vous permet d'afficher une somme d'argent en USD. Dans cette situation, vous pouvez faire quelque chose comme ce qui suit :
>>> Template("${amount}USD").substitute(amount="100")
'100USD'
>>> Template("$amountUSD").substitute(amount="100")
Traceback (most recent call last):
...
KeyError: 'amountUSD'
Étant donné que USD
sont tous des caractères que vous pouvez utiliser dans un identifiant Python valide, vous devez utiliser le style d'espace réservé $ {identifier>
. Sinon, vous obtenez une KeyError
.
Enfin, la chaîne de modèle que vous fournissez au constructeur Template()
est stockée dans l'attribut .template
. Cela vous permet de modifier le modèle de manière dynamique :
>>> greeting = Template("Hello, $name! Today is $day.")
>>> greeting.substitute(name="John", day="Friday")
'Hello, John! Today is Friday.'
>>> greeting.template = "Hello, $name! Welcome!"
>>> greeting.substitute(name="John")
'Hello, John! Welcome!'
Vous pouvez modifier l'attribut .template
chaque fois que vous en avez besoin. Cependant, il est préférable de créer de nouvelles instances de Template
pour chaque chaîne de modèle différente dans votre code. De cette façon, vous éviterez des bugs subtils ou même la rupture de vos modèles.
Remplacement des valeurs par .substitute()
Jusqu'à présent, vous avez utilisé la méthode .substitute()
avec des arguments de mots-clés pour interpoler les valeurs dans vos modèles de chaînes. Vous pouvez également utiliser les méthodes avec des dictionnaires :
>>> from string import Template
>>> numbers = {"one": 1, "two": 2, "three": 3}
>>> Template("$one-$two-$three").substitute(**numbers)
'1-2-3'
Encore une fois, lorsque vous utilisez un dictionnaire comme argument pour substitute()
, vous devez utiliser l'opérateur de décompression du dictionnaire (**
). Cet opérateur décompressera les paires clé-valeur en arguments de mots-clés qui seront insérés dans les espaces réservés appropriés dans la chaîne du modèle.
Notez que les noms des espaces réservés doivent correspondre aux clés du dictionnaire. Si un espace réservé ne correspond à aucune clé ou si le nombre de clés ne correspond pas au nombre d'espaces réservés, vous obtenez une erreur :
>>> numbers = {"one": 1, "two": 2}
>>> Template("$one-$two-$three").substitute(**numbers)
Traceback (most recent call last):
...
KeyError: 'three'
Si vous appelez .substitute()
avec un dictionnaire dont les clés ne correspondent pas à tous les espaces réservés dans la chaîne du modèle, alors vous obtenez une KeyError
.
Remplacement des valeurs par .safe_substitute()
Template
a une autre méthode que vous pouvez utiliser pour interpoler les valeurs dans le modèle de chaîne. La méthode s'appelle .safe_substitute()
et fonctionne de manière similaire à .substitute()
. Cependant, lorsque vous utilisez un ensemble d'arguments incomplet ou ne correspondant pas, la méthode ne génère pas de KeyError
:
>>> from string import Template
>>> numbers = {"one": 1, "two": 2}
>>> Template("$one-$two-$three").safe_substitute(**numbers)
'1-2-$three'
Dans cet extrait de code, vous appelez .safe_substitute()
en utilisant un dictionnaire dont les clés ne correspondent pas à tous les espaces réservés existants. Plutôt que d'obtenir une exception KeyError
, vous obtenez une chaîne qui montre littéralement l'espace réservé manquant. Cela peut être utile pour identifier les valeurs manquantes dans une vue d'une page HTML à restituer.
La méthode .safe_substitute()
pourrait être un avantage de l'utilisation de Template
par rapport à la méthode .format()
:
>>> "{one}-{two}-{three}".format(**numbers)
Traceback (most recent call last):
...
KeyError: 'three'
La méthode .format()
ne dispose pas d'un moyen sûr d'effectuer l'interpolation lorsque vous utilisez un ensemble d'arguments incomplet ou ne correspondant pas.
Conclusion
Vous avez appris à effectuer une interpolation de chaînes et à créer de nouvelles chaînes en insérant des objets dans un modèle de chaîne. Vous savez maintenant que Python dispose de plusieurs outils pour l’interpolation de chaînes. Ces outils incluent les f-strings, la méthode str.format()
et l'opérateur modulo (%
).
Vous avez également découvert la classe Template
, que vous pouvez également utiliser pour l'interpolation de chaînes. Cette classe est fournie dans un module de bibliothèque standard appelé string
.
Dans ce didacticiel, vous avez :
- J'ai appris à utiliser les f-strings pour une interpolation empressée de chaînes.
- Interpolation de chaîne paresseuse avec
str.format()
- Utilisé l'opérateur modulo (
%
) pour l'interpolation de chaîne - J'ai appris quand utiliser des f-strings ou
str.format()
pour l'interpolation. - Interpolation de chaîne terminée avec la classe
string.Template
Vous disposez désormais des compétences requises pour commencer à créer des chaînes à l’aide de différents outils d’interpolation. L'outil que vous utiliserez dépendra de votre cas d'utilisation spécifique.