Interpolation de variables dans les chaînes de caractères en Python

Dans cet article, vous allez apprendre comment créer une chaîne de caractères dans laquelle des noms de variables sont intégrés et substitués par une représentation sous forme de chaîne de caractères de la valeur d’une variable.

Python n’a pas de support direct pour substituer des valeurs de variables dans les chaînes de caractères. Cependant, cette caractéristique peut être approchée à l’aide de la méthode format() de la classe str des chaînes de caractères. Par exemple:

>>> s = '{nom} a {n} messages.'
>>> s.format(nom='Fred', n=27)
'Fred a 27 messages.'
>>>

 

Alternativement, si les valeurs à substituer se trouvent vraiment dans des variables, vous pouvez utiliser la combinaison des méthodes format_map() et vars(), comme dans l’exemple qui suit :

>>> nom = 'Fred'
>>> n = 37
>>> s.format_map(vars())
'Fred a 37 messages.'
>>>

 

Une caractéristique subtile de vars() est qu’il fonctionne aussi avec les instances. Par exemple:

>>> class Info:
... 	def __init__(self, nom, n):
... 		self.nom = nom
... 		self.n = n
...
>>> a = Info('Fred',27)
>>> s.format_map(vars(a))
'Fred a 27 messages.'
>>>

 

Un inconvénient de format() et format_map() est qu’elles ne traitent pas élégamment les valeurs manquantes. Par exemple:

>>> s.format(nom='Fred')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'n'
>>>

 

Une façon d’éviter cela est de définir une classe alternative dictionnaire avec une méthode __missing__(), comme dans ce qui suit :

Utilisez maintenant cette classe pour encapsuler les entrées dans format_map() :

Si vous effectuez fréquemment ces étapes dans votre code, vous pouvez cacher le processus de substitution de variables derrière une petite fonction utilitaire qui utilise une fonction dite “frame hack”. Par exemple:

class safesub(dict):
   def __missing__(self, cle):
      return '{' + cle + '}'

 

Maintenant, vous pouvez taper quelque chose comme suit :

>>> del n # S'assurer que n est indéfini
>>> s.format_map(safesub(vars()))
'Fred a {n} messages.'
>>>

 

Si vous effectuez fréquemment ces étapes dans votre code, vous pouvez cacher le processus de substitution de variables derrière une petite fonction utilitaire qui utilise une fonction dite “frame hack”. Par exemple:

import sys
def sub(text):
   return text.format_map(safesub(sys._getframe(1).f_locals))

 

Maintenant, vous pouvez taper quelque chose comme suit:

>>> nom = 'Fred'
>>> n = 27
>>> print(sub('Bonjour {nom}'))
Bonjour Fred
>>> print(sub('Vous avez {n} messages.'))
Vous avez 27 messages.
>>> print(sub('Votre couleur préférée est {couleur}'))
Votre couleur préférée est {couleur}
>>>

 

L’absence d’interpolation réelle de variables en Python a conduit à une variété de solutions au fil des années. Comme alternative à la solution présentée dans cet exemple, vous verrez parfois le formatage des chaînes de caractères comme ceci :

>>> nom = 'Fred'
>>> n = 27
>>> '%(nom) a %(n) messages.' % vars()
'Fred a 27 messages.'
>>>

 

Vous pouvez également voir l’utilisation de chaînes de caractères modèles :

>>> import string
>>> s = string.Template('$nom a $n messages.')
>>> s.substitute(vars())
'Fred a 27 messages.'
>>>

 

Cependant, les méthodes format() et format_map() sont plus modernes que l’une ou l’autre de ces alternatives, et devraient être privilégiées.

Un avantage de l’utilisation de format() est que vous obtenez également toutes les fonctionnalités liées au formatage des chaînes de caractères (alignement, remplissage, formatage numérique, etc.), ce qui n’est tout simplement pas possible avec des alternatives telles que les objets de chaînes de caractères Template.

Certaines parties de cet exemple illustrent également quelques fonctions avancées intéressantes. La méthode peu connue __missing__() des classes mapping/dict est une méthode que vous pouvez définir pour gérer les valeurs manquantes.

Dans la classe safesub, cette méthode a été définie pour renvoyer les valeurs manquantes en tant que caractère de remplissage.

Au lieu d’obtenir une exception KeyError, vous verriez les valeurs manquantes apparaître dans la chaîne résultante (potentiellement utile pour le débogage).

La fonction sub() utilise sys._getframe(1) pour retourner la pile de l’appelant. A partir de là, on accède à l’attribut f_locals pour obtenir les variables locales. Il est clair qu’il faut probablement éviter de jouer avec les piles dans la plupart des codes.

Cependant, pour les fonctions utilitaires telles qu’une fonctionnalité de substitution de chaîne de caractères, elle peut être utile. Par ailleurs, il est probablement intéressant de noter que f_locals est un dictionnaire qui est une copie des variables locales dans la fonction appelante.

Bien que vous puissiez modifier le contenu de f_locals, les modifications n’ont pas d’effet durable. Ainsi, même si l’accès à une pile différente peut sembler malveillant, il n’est pas possible d’écraser accidentellement des variables ou de modifier l’environnement local de l’appelant.

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here