¿Hay un Python equivalente a la interpolación de cadenas de Ruby?

343

Ruby ejemplo:

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

La exitosa concatenación de cadenas de Python es aparentemente detallada para mí.

Casta
fuente
2
El problema aquí es que namees una variable local que se encuentra en la cadena, y en Python tienes que pasar explícitamente el diccionario de variables locales al formateador de cadena si quieres que las use.
Katriel
Este no era el problema original, pero gracias. Su comentario me dio una mejor comprensión del alcance variable (algo con lo que todavía estoy ganando terreno). :)
Casta
1
¿Qué opinas de este, entonces? stackoverflow.com/questions/16504732/…
SalchiPapa
2
Consulte stackoverflow.com/a/33264516/55721 para ver esta característica exacta en 3.6
dss539

Respuestas:

413

Python 3.6 agregará una interpolación de cadena literal similar a la interpolación de cadena de Ruby. A partir de esa versión de Python (que se lanzará a finales de 2016), podrá incluir expresiones en "cadenas f", por ejemplo

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

Antes de 3.6, lo más cercano que puede llegar a esto es

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

El %operador se puede usar para la interpolación de cadenas en Python. El primer operando es la cadena a interpolar, el segundo puede tener diferentes tipos, incluyendo un "mapeo", mapeando los nombres de los campos a los valores a ser interpolados. Aquí utilicé el diccionario de variables locales locals()para asignar el nombre del campo namea su valor como variable local.

El mismo código que usa el .format()método de las versiones recientes de Python se vería así:

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

También está la string.Templateclase:

tmpl = string.Template("Who lives in a Pineapple under the sea? $name.")
print(tmpl.substitute(name="Spongebob Squarepants"))
Sven Marnach
fuente
@Caste vea aquí: docs.python.org/library/stdtypes.html#string-formatting y publique un comentario de seguimiento si necesita más detalles
mikej
Entiendo la esencia básica de esto, sin embargo, no entiendo completamente todos los símbolos y textos adicionales encontrados en el ejemplo en la documentación. ¿Por qué el uso de convertir a cadena aquí:% (idioma) s ¿Qué significa el 3 en '03d'? ¿Por qué después de la cadena hay% \? La asignación de variables (si de hecho son variables) después de la expresión de impresión también me confunde. Lo siento si esto es un dolor!
Casta
1
Los dos formatos básicos utilizados en el ejemplo son %spara una cadena y %03dpara un número rellenado con 3 dígitos con ceros a la izquierda. Podría simplemente ser escrito print "%s has %03d" % ("Python", 2). Luego, el ejemplo hace uso de poner una clave de mapeo entre paréntesis después de lo %cual es una forma de dar nombres significativos a los marcadores de posición en lugar de confiar en su orden en la cadena. Luego pasa un diccionario que asigna los nombres clave a sus valores. Es por eso que Sven está utilizando la locals()función que devuelve un dict que contiene todas sus variables locales para que se name
asigne
El uso requerido de un tipo de conversión fue lo que primero me confundió. Entonces, usando la terminología de la documentación. El% inicia el especificador. No hay un indicador de conversión para (idioma), solo un tipo de conversión (la 's' posterior); (número) sin embargo tiene uno (o dos) indicadores de conversión que es '0' (y '3' respectivamente). La 'd' es el tipo de conversión y significa que es un número entero. ¿Lo entendí correctamente?
Casta
@Caste: Sí, eso es básicamente correcto. Tenga en cuenta que siempre puede usar a scomo tipo de conversión: Python puede convertir casi cualquier cosa en una cadena. Pero, por supuesto, perdería las capacidades especiales de formato de otros tipos de conversión.
Sven Marnach
143

Desde Python 2.6.X es posible que desee utilizar:

"my {0} string: {1}".format("cool", "Hello there!")
EinLama
fuente
27
Tenga en cuenta que el %operador para la interpolación de cadenas no está en desuso en Python 3.x. docs.python.org/dev/py3k/whatsnew/… anuncia el plan para desaprobar a %partir de 3.1, pero esto nunca sucedió.
Sven Marnach
8
% -syntax sigue vivo en Python 3 (no obsoleto a partir de Python 3.2)
Corey Goldberg
99
Solo una nota: el número {}puede eliminarme.
sorteo
32

Desarrollé el paquete interpy , que permite la interpolación de cadenas en Python .

Simplemente instálelo a través de pip install interpy. ¡Y luego, agregue la línea # coding: interpyal comienzo de sus archivos!

Ejemplo:

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

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n#{name}."
Syrus Akbary Nieto
fuente
3
Esto parece realmente inseguro.
d33tah
@ d33tah: No, siempre que las cadenas se conozcan en tiempo de compilación.
Clément
28

La interpolación de cadenas de Python es similar a la de printf () de C

Si intentas:

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

La etiqueta %sse reemplazará con la namevariable. Debe echar un vistazo a las etiquetas de función de impresión: http://docs.python.org/library/functions.html

Oleiade
fuente
1
¿Cómo puedo hacer esto con 2 variables?
Julio Marins
16
@JulioMarins Utilice una tupla: print "First is %s, second is %s" % (var1, var2).
kirbyfan64sos
28

La interpolación de cadenas se incluirá con Python 3.6 como se especifica en PEP 498 . Podrás hacer esto:

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

Tenga en cuenta que odio a Bob Esponja, por lo que escribir esto fue un poco doloroso. :)

kirbyfan64sos
fuente
Gracias por esa referencia de Bob Esponja (/ distaste): tengo que votar esto ahora.
javadba
4

También puedes tener esto

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
fuente
No creo que OP pretendiera #que se imprimiera. Solo están usando la sintaxis de Ruby.
jaynp
Tienes razón. Edité la respuesta. No estoy familiarizado con Ruby, así que pensé que el #personaje sería impreso.
Quan al
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)

Uso:

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

PD: el rendimiento puede ser un problema. Esto es útil para scripts locales, no para registros de producción.

Duplicado:

Paulo Check
fuente
2

Para el antiguo Python (probado en 2.4), la mejor solución señala el camino. Puedes hacerlo:

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()

Y tu obtienes

d: 1 f: 1.1 s: s
Michael Fox
fuente