¿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í.


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

@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!")

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}."

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


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



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:


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.