Existe-t-il un Python équivalent à l'interpolation de chaînes de Ruby?

343

Exemple Ruby:

name = "Spongebob Squarepants"
puts "Who lives in a Pineapple under the sea? \n#{name}."

La concaténation réussie de la chaîne Python est apparemment verbeuse pour moi.

Caste
la source
2
Le problème ici est qu'il names'agit d'une variable locale située dans la chaîne, et en Python, vous devez passer explicitement le dictionnaire des variables locales au formateur de chaînes si vous voulez qu'il les utilise.
Katriel
Ce n'était pas le problème d'origine, mais merci. Votre commentaire m'a permis de mieux comprendre la portée variable (quelque chose avec laquelle je gagne encore du terrain). :)
Caste du
1
Que pensez-vous de celui-ci, alors? stackoverflow.com/questions/16504732/…
SalchiPapa
2
Voir stackoverflow.com/a/33264516/55721 pour cette fonctionnalité exacte dans 3.6
dss539

Réponses:

413

Python 3.6 ajoutera une interpolation de chaîne littérale similaire à l'interpolation de chaîne de Ruby. À partir de cette version de Python (dont la sortie est prévue fin 2016), vous pourrez inclure des expressions dans les "f-strings", par exemple

name = "Spongebob Squarepants"
print(f"Who lives in a Pineapple under the sea? {name}.")

Avant la 3.6, le plus proche de vous est

name = "Spongebob Squarepants"
print("Who lives in a Pineapple under the sea? %(name)s." % locals())

L' %opérateur peut être utilisé pour l' interpolation de chaînes en Python. Le premier opérande est la chaîne à interpoler, le second peut avoir différents types, y compris un "mappage", mappant les noms de champ aux valeurs à interpoler. Ici, j'ai utilisé le dictionnaire des variables locales locals()pour mapper le nom du champ nameà sa valeur en tant que variable locale.

Le même code utilisant la .format()méthode des versions récentes de Python ressemblerait à ceci:

name = "Spongebob Squarepants"
print("Who lives in a Pineapple under the sea? {name!s}.".format(**locals()))

Il y a aussi la string.Templateclasse:

tmpl = string.Template("Who lives in a Pineapple under the sea? $name.")
print(tmpl.substitute(name="Spongebob Squarepants"))
Sven Marnach
la source
@Caste voir ici: docs.python.org/library/stdtypes.html#string-formatting et publier un commentaire de suivi si vous avez besoin de plus de détails
mikej
J'en comprends l'essentiel, je ne comprends pas complètement tous les symboles et textes supplémentaires trouvés dans l'exemple de la documentation. Pourquoi utiliser convert en chaîne ici:% (langue) s Que signifie le 3 dans '03d'? Pourquoi après la chaîne y a-t-il% \? L'affectation de variables (s'il s'agit en fait de variables) après l'expression imprimée me trouble également. Désolé si c'est une douleur!
Caste
1
Les deux formats de base utilisés dans l'exemple sont %spour une chaîne et %03dpour un nombre complété à 3 chiffres avec des zéros en tête. Cela pourrait simplement être écrit print "%s has %03d" % ("Python", 2). L'exemple utilise ensuite de mettre une clé de mappage entre crochets après le %qui est un moyen de donner aux espaces réservés des noms significatifs plutôt que de se fier à leur ordre dans la chaîne. Vous passez ensuite un dictionnaire qui mappe les noms de clé à leurs valeurs. C'est pourquoi Sven utilise la locals()fonction qui retourne un dict contenant toutes vos variables locales afin qu'il soit mappé nameà la valeur du nom
mikej
L'utilisation requise d'un type de conversion est ce qui m'a le plus troublé. Donc, en utilisant la terminologie de la documentation. Le% démarre le spécificateur. Il n'y a pas d'indicateur de conversion pour (langue), juste un type de conversion (les «derniers»); (nombre) a cependant un (ou deux) drapeaux de conversion qui est «0» (et «3» respectivement). Le «d» est le type de conversion et signifie qu'il s'agit d'un entier. Ai-je bien compris?
Caste
@Caste: Oui, c'est fondamentalement vrai. Notez que vous pouvez toujours utiliser un scomme type de conversion - Python peut convertir à peu près n'importe quoi en chaîne. Mais bien sûr, vous perdriez les capacités de formatage spéciales des autres types de conversion.
Sven Marnach
143

Depuis Python 2.6.X, vous pouvez utiliser:

"my {0} string: {1}".format("cool", "Hello there!")
EinLama
la source
27
Notez que l' %opérateur d'interpolation de chaîne n'est pas obsolète dans Python 3.x. docs.python.org/dev/py3k/whatsnew/… annonce le plan de dépréciation à %partir de la 3.1, mais cela ne s'est jamais produit.
Sven Marnach
8
% -syntax persiste dans Python 3 (non obsolète depuis Python 3.2)
Corey Goldberg
9
Juste une note: le nombre {}peut être éliminé.
tirage au sort
32

J'ai développé le paquet interpy , qui permet l'interpolation de chaînes en Python .

Installez-le via pip install interpy. Et puis, ajoutez la ligne # coding: interpyau début de vos fichiers!

Exemple:

#!/usr/bin/env python
# coding: interpy

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n#{name}."
Syrus Akbary Nieto
la source
3
Cela semble vraiment peu sûr.
d33tah
@ d33tah: Non, tant que les chaînes sont connues au moment de la compilation.
Clément
28

L'interpolation de chaînes de Python est similaire à printf () de C

Si tu essayes:

name = "SpongeBob Squarepants"
print "Who lives in a Pineapple under the sea? %s" % name

La balise %ssera remplacée par la namevariable. Vous devriez jeter un œil aux balises de fonction d'impression: http://docs.python.org/library/functions.html

Oleiade
la source
1
comment puis-je faire de cette façon avec 2 variables?
Julio Marins
16
@JulioMarins Utilisez un tuple: print "First is %s, second is %s" % (var1, var2).
kirbyfan64sos
28

L'interpolation de chaînes va être incluse avec Python 3.6 comme spécifié dans PEP 498 . Vous pourrez le faire:

name = 'Spongebob Squarepants'
print(f'Who lives in a Pineapple under the sea? \n{name}')

Notez que je déteste Spongebob, donc écrire cela a été légèrement douloureux. :)

kirbyfan64sos
la source
Thx pour cette référence Spongebob (/ distaste): dois voter maintenant.
javadba
4

Vous pouvez également avoir ceci

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n{name}.".format(name=name)

http://docs.python.org/2/library/string.html#formatstrings

Quan To
la source
Je ne pense pas qu'OP ait voulu l' #imprimer. Ils utilisent simplement la syntaxe Ruby.
jaynp
Vous avez raison. J'ai édité la réponse. Je ne connais pas Ruby, donc j'ai pensé que le #personnage serait imprimé.
Quan au
3
import inspect
def s(template, **kwargs):
    "Usage: s(string, **locals())"
    if not kwargs:
        frame = inspect.currentframe()
        try:
            kwargs = frame.f_back.f_locals
        finally:
            del frame
        if not kwargs:
            kwargs = globals()
    return template.format(**kwargs)

Usage:

a = 123
s('{a}', locals()) # print '123'
s('{a}') # it is equal to the above statement: print '123'
s('{b}') # raise an KeyError: b variable not found

PS: les performances peuvent être un problème. Ceci est utile pour les scripts locaux, pas pour les journaux de production.

Dupliqué:

Paulo Check
la source
2

Pour l'ancien Python (testé sur 2.4), la meilleure solution montre le chemin. Tu peux le faire:

import string

def try_interp():
    d = 1
    f = 1.1
    s = "s"
    print string.Template("d: $d f: $f s: $s").substitute(**locals())

try_interp()

Et vous obtenez

d: 1 f: 1.1 s: s
Michael Fox
la source