Comment reporter/différer l'évaluation des f-strings ?

J'utilise des chaînes de modèle pour générer des fichiers et j'aime la concision des nouvelles chaînes f à cet effet, pour réduire mon code de modèle précédent à partir de quelque chose comme ceci :

template_a = "The current name is {name}"
names = ["foo", "bar"]
for name in names:
print (template_a.format(**locals()))

Maintenant, je peux le faire, en remplaçant directement les variables :

names = ["foo", "bar"]
for name in names:
print (f"The current name is {name}")

Cependant, il est parfois logique d'avoir le modèle défini ailleurs - plus haut dans le code, ou importé à partir d'un fichier ou quelque chose. Cela signifie que le modèle est une chaîne statique contenant des balises de formatage. Quelque chose devrait arriver à la chaîne pour dire à l'interpréteur d'interpréter la chaîne comme une nouvelle chaîne f, mais je ne sais pas s'il existe une telle chose.

Existe-t-il un moyen d'introduire une chaîne et de la faire interpréter comme une chaîne f pour éviter d'utiliser l' .format(**locals())appel?

Idéalement, je veux pouvoir coder comme ça... (où magic_fstring_functionest la partie que je ne comprends pas):

template_a = f"The current name is {name}"
# OR [Ideal2] template_a = magic_fstring_function(open('template.txt').read())
names = ["foo", "bar"]
for name in names:
print (template_a)

... avec cette sortie souhaitée (sans lire le fichier deux fois):

The current name is foo
The current name is bar

... mais la sortie réelle que j'obtiens est:

The current name is {name}
The current name is {name}


Solution du problème

Une manière concise d'avoir une chaîne évaluée comme une f-string (avec toutes ses capacités) utilise la fonction suivante :

def fstr(template):
return eval(f"f'{template}'")

Ensuite tu peux faire:

template_a = "The current name is {name}"
names = ["foo", "bar"]
for name in names:
print(fstr(template_a))
# The current name is foo
# The current name is bar

Et, contrairement à de nombreuses autres solutions proposées, vous pouvez également faire:

template_b = "The current name is {name.upper() * 2}"
for name in names:
print(fstr(template_b))
# The current name is FOOFOO
# The current name is BARBAR

Commentaires

Posts les plus consultés de ce blog

Erreur Symfony : "Une exception a été levée lors du rendu d'un modèle"

Détecter les appuis sur les touches fléchées en JavaScript

Une chaîne vide donne "Des erreurs ont été détectées dans les arguments de la ligne de commande, veuillez vous assurer que tous les arguments sont correctement définis"