¿Cuál es la diferencia entre estas dos declaraciones de formato de cadena en Python:
'{0}'.format(a) '{0!s}'.format(a)
Ambos tienen la misma salida si a
es un número entero, una lista o un diccionario. ¿El primero {0}
haciendo una llamada implícita a str()
?
Fuente
PD: palabras clave: exclamación / bang “! S” formateando
Se menciona en la documentación:
El campo de conversión provoca una coacción de tipo antes de formatear. Normalmente, el trabajo de formatear un valor se realiza mediante el
__format__()
del propio valor. Sin embargo, en algunos casos es conveniente forzar el formato de un tipo como una cadena, anulando su propia definición de formato. Al convertir el valor en una cadena antes de llamar__format__()
, se omite la lógica de formato normal.Actualmente se admiten dos indicadores de conversión: ‘
!s
‘ que llama astr()
en el valor, y ‘!r
‘ que llama arepr()
.
Se puede tomar un ejemplo (nuevamente de la documentación ) para mostrar la diferencia:
>>> "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2') "repr() shows quotes: 'test1'; str() doesn't: test2"
Dicho simplemente:
'{0}'.format(a)
usará el resultado de a.__format__()
para mostrar el valor '{0!s}'.format(a)
usará el resultado de a.__str__()
para mostrar el valor '{0!r}'.format(a)
usará el resultado de a.__repr__()
para mostrar el valor >>> class C: ... def __str__(self): return "str" ... def __repr__(self): return "repr" ... def __format__(self, format_spec): return "format as " + str(type(format_spec)) ... >>> c = C() >>> print "{0}".format(c) format as >>> print u"{0}".format(c) format as >>> print "{0!s}".format(c) str >>> print "{0!r}".format(c) repr
Con respecto al segundo argumento de __format__
, para citar PEP 3101 “Controlar el formateo en una base por tipo” :
El argumento ‘format_spec’ será un objeto de cadena o un objeto Unicode, dependiendo del tipo de cadena de formato original. El método
__format__
debe probar el tipo de parámetro de los especificadores para determinar si se debe devolver una cadena o un objeto Unicode. Es responsabilidad del método__format__
devolver un objeto del tipo adecuado.
Gracias al comentario y la respuesta de @ hjpotter92 por la explicación:
Aquí hay un ejemplo que muestra la diferencia (es cuando reemplaza el método __format__
)
class MyClass: i = 12345 def __format__(self, i): return 'I Override' >>> obj = MyClass() >>> '{0}'.format(obj) 'I Override' >>> '{0!s}'.format(obj) '<__main__.MyClass instance at 0x021AA6C0>'