¿Es posible hacer un formateo parcial de cadenas con los métodos avanzados de formateo de cadenas, similar a la plantilla de cadena safe_substitute()
función de ?
Por ejemplo:
s = '{foo} {bar}'
s.format(foo='FOO') #Problem: raises KeyError 'bar'
python
string-formatting
P3trus
fuente
fuente
{bar:1.2f}
__missing__()
, devuelva una instancia de una clase personalizada que sobrescriba__format__()
de manera que devuelva el marcador de posición original, incluida la especificación de formato. Prueba de concepto: ideone.com/xykV7RSi sabe en qué orden está formateando las cosas:
Úselo así:
No puede especificar
foo
y,bar
al mismo tiempo, debe hacerlo secuencialmente.fuente
s.format(foo='FOO',bar='BAR')
entonces todavía tengo'FOO {bar}'
, no importa qué. ¿Podrías aclararlo?Podrías usar la
partial
función desde lafunctools
cual es corta, más legible y también describe la intención del codificador:fuente
python from functool import partial s = "{foo} {bar}".format s_foo = partial(s, foo="FOO") print(s_foo(bar="BAR")) # FOO BAR print(s(foo="FOO", bar="BAR")) # FOO BAR
partial()
no me va a ayudar si necesito hacer un procesamiento con la cadena parcialmente formateada (es decir"FOO {bar}"
)."{foo} {{bar}}".format(foo="{bar}").format(bar="123")
de los otros ejemplos. Yo esperaría"{bar} 123"
pero salen"123 123"
.Esta limitación de
.format()
la incapacidad de hacer sustituciones parciales me ha estado molestando.Después de evaluar escribir una
Formatter
clase personalizada como se describe en muchas respuestas aquí e incluso considerar el uso de paquetes de terceros como lazy_format , descubrí una solución incorporada mucho más simple: cadenas de plantillasProporciona una funcionalidad similar pero también proporciona un
safe_substitute()
método completo de sustitución parcial . Las cadenas de plantilla deben tener un$
prefijo (que se siente un poco extraño, pero la solución general creo que es mejor).Formó una envoltura de conveniencia basada en esto:
Del mismo modo, un contenedor basado en la respuesta de Sven que utiliza el formato de cadena predeterminado:
fuente
No estoy seguro si esto está bien como una solución rápida, pero ¿qué tal
? :)
fuente
Si define el suyo propio
Formatter
que anula elget_value
método, puede usarlo para asignar nombres de campo indefinidos a lo que desee:http://docs.python.org/library/string.html#string.Formatter.get_value
Por ejemplo, podría asignar
bar
a"{bar}"
sibar
no está en los kwargs.Sin embargo, eso requiere usar el
format()
método de su objeto Formatter, no elformat()
método de la cadena .fuente
Probar esto.
fuente
{{
y}}
es una forma de escapar de las marcas de formato, por loformat()
que no realiza sustitución y reemplaza{{
y}}
con{
y}
, respectivamente.{{ }}
solo funciona para un formato, si necesita aplicar más, necesitará agregar más{}
. ex.'fd:{uid}:{{topic_id}}'.format(uid=123).format(a=1)
devolverá un error ya que el segundo formato no proporciona eltopic_id
valor.Gracias al comentario de Amber , se me ocurrió esto:
fuente
{field!s: >4}
convierte en{field}
Para mí esto fue lo suficientemente bueno:
fuente
Todas las soluciones que he encontrado parecen tener problemas con especificaciones más avanzadas u opciones de conversión. @ SvenMarnach de FormatPlaceholder es maravillosamente inteligente, pero no funciona correctamente con la coacción (por ejemplo
{a!s:>2s}
), ya que llama al__str__
método (en este ejemplo) en lugar de__format__
y se pierde cualquier formato adicional.Esto es lo que terminé y algunas de sus características clave:
str.format
(no solo un mapeo){k!s}
{!r}
{k:>{size}}
{k.foo}
{k[0]}
{k!s:>{size}}
Descubrí los problemas con las diversas implementaciones después de escribir algunas pruebas sobre cómo quería que se comportara este método. Están debajo si alguien los encuentra perspicaces.
fuente
Mi sugerencia sería la siguiente (probado con Python3.6):
Actualización: aquí se muestra una forma aún más elegante (subclasificación
dict
y sobrecarga__missing__(self, key)
): https://stackoverflow.com/a/17215533/333403fuente
Suponiendo que no usará la cadena hasta que esté completamente llena, podría hacer algo como esta clase:
Ejemplo:
fuente
Hay una forma más de lograr esto, es decir, usando
format
y%
reemplazando variables. Por ejemplo:fuente
Una solución muy fea pero la más simple para mí es simplemente hacer:
De esta manera, todavía puede usar
tmpl
como plantilla regular y realizar un formateo parcial solo cuando sea necesario. Este problema me parece demasiado trivial para usar una solución exagerada como la de Mohan Raj.fuente
Después de probar las soluciones más prometedoras de aquí y de allá , me di cuenta de que ninguna de ellas realmente cumplía con los siguientes requisitos:
str.format_map()
para la plantilla;Entonces, escribí mi propia solución, que satisface los requisitos anteriores. ( EDITAR : ahora la versión de @SvenMarnach, como se informa en esta respuesta, parece manejar los casos de esquina que necesitaba).
Básicamente, terminé analizando la cadena de plantilla, encontrando
{.*?}
grupos anidados coincidentes (usando unafind_all()
función auxiliar) y construyendo la cadena formateada de manera progresiva y directa usandostr.format_map()
mientras detectaba cualquier potencialKeyError
.(Este código también está disponible en FlyingCircus - DESCARGO DE RESPONSABILIDAD: soy el autor principal de la misma).
El uso de este código sería:
Comparemos esto con mi solución favorita (por @SvenMarnach que amablemente compartió su código aquí y allá ):
Aquí hay un par de pruebas:
y el código para hacerlo funcionar:
Resultando en:
Como puede ver, la versión actualizada ahora parece manejar bien los casos de esquina donde la versión anterior solía fallar.
En el tiempo, están dentro de aprox. 50% el uno del otro, dependiendo del
text
formato real (y probablemente el realsource
), perosafe_format_map()
parece tener una ventaja en la mayoría de las pruebas que realicé (lo que sea que signifiquen, por supuesto):fuente
{d[x]}
por lo que sé, no es una cadena de formato válida.field_name ::= arg_name ("." attribute_name | "[" element_index "]")*
y ambosstr.format()
y lostr.format_map()
entienden. Yo diría que hay suficiente evidencia de que esta es una cadena de formato válida.str.format()
con un índice no entero entre corchetes? Solo puedo hacer que funcionen los índices enteros.a = dict(b='YAY!'); '{a[b]}'.format_map(dict(a=a))
te pone `` ¡YAY! ''a[b]
en el código Python, pero en realidad esa["b"]
¡Gracias!Si desea descomprimir un diccionario para pasar argumentos
format
, como en esta pregunta relacionada , puede usar el siguiente método.Primero suponga que la cadena
s
es la misma que en esta pregunta:y los valores están dados por el siguiente diccionario:
Claramente esto no funcionará:
Sin embargo, primero puede obtener uno
set
de todos los argumentos nombradoss
y crear un diccionario que asigne el argumento a sí mismo envuelto en llaves:Ahora use el
args
diccionario para completar las claves que faltanreplacements
. Para python 3.5+, puede hacer esto en una sola expresión :Para versiones anteriores de python, puede llamar a
update
:fuente
Me gusta la respuesta de @ sven-marnach. Mi respuesta es simplemente una versión extendida de la misma. Permite el formato sin palabras clave e ignora las claves adicionales. Aquí hay ejemplos de uso (el nombre de una función es una referencia al formato de cadena f de python 3.6):
Y aquí está mi código:
fuente
Si está haciendo muchas plantillas y encuentra que la funcionalidad de plantilla integrada de Python es insuficiente o torpe, mire Jinja2 .
De los documentos:
fuente
Leyendo el comentario de @Sam Bourne, modifiqué el código de @SvenMarnach para que funcione correctamente con la coerción (me gusta
{a!s:>2s}
) sin escribir un analizador personalizado. La idea básica no es convertir a cadenas, sino concatenar las claves que faltan con etiquetas de coerción.Use (por ejemplo) como este
Las siguientes pruebas (inspiradas en las pruebas de @ norok2) verifican el resultado para el tradicional
format_map
y elsafe_format_map
basado en la clase anterior en dos casos: proporcionando palabras clave correctas o sin ellas.Que salidas
fuente
Podría envolverlo en una función que tome argumentos predeterminados:
fuente