Formateo de cadenas con Python

Tarde o temprano, el formateo de cadenas se convierte en un mal necesario para la mayoría de los programadores. Más aún en el pasado antes de la era de la GUI de cliente pesado, pero la necesidad de tener un sp ...

Introducción

Tarde o temprano, el formateo de cadenas se convierte en un mal necesario para la mayoría de los programadores. Más aún en el pasado, antes de la era de la GUI de cliente grueso, pero la necesidad de tener una representación de cadena específica sigue siendo un caso de uso bastante común. Mi primera presentación fue en la universidad cuando tenía un profesor de la vieja escuela que tenía un amor impuro por hacernos escribir aplicaciones de consola Java con especificaciones neuróticas para generar con la función printf (...). Una cosa que era cierta entonces y todavía lo es ahora es que la documentación para el formato de cadenas (prácticamente para todos los idiomas) deja mucho que desear. Espero aliviar este dolor hoy escribiendo sobre cómo lograr el formato de cadenas en Python.

En Python, existen múltiples técnicas para formatear cadenas, cuatro para ser exactos. Curiosamente, esto va en contra de la mentalidad de Python de que, en general, debería haber una mejor manera clara de realizar una tarea. Sin embargo, si ha pasado una cantidad de tiempo razonable con el idioma, es probable que haya visto esta variedad dispar de técnicas y se haya preguntado, “¿cuál es el problema con todo esto?”.

Repaso de las técnicas de formato de cuatro cadenas {#repaso de las técnicas de formato de cuatro cadenas}

Comencemos con el método más comúnmente visto que usa el operador %. Digo el más común simplemente porque ha existido por más tiempo y lo ves por todas partes (libros, publicaciones de blog, desbordamiento de pila, etc.). Para utilizar este método, especifique un marcador de posición en una cadena usando %s para cadenas y %d para números.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
>>> "Hello reader, welcome to the %s form of string formatting." % 'modulus'
'Hello reader, welcome to the modulus form of string formatting.'
>>>
>>> "Formatting multiple (%d, %d, %d, ...) values requires a %s." % (1, 2, 3, 'tuple')
'Formatting multiple (1, 2, 3, ...) values requires a tuple.'
>>>
>>> print("""If you prefer named placeholders for values %(one)d, %(two)d,
... %(three)d ... you can use a dict""" % {'one':1, 'two':2, 'three':3})
If you prefer named placeholders for values 1, 2,
3 ... you can use a dict

La siguiente técnica a cubrir es el método str.format(...). Esto estaba destinado a ser el reemplazo del estilo % que se mostró anteriormente. Esta técnica utiliza el designador de corchetes {} para especificar dónde y cómo formatear un valor en una cadena.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
>>> "Hello reader, welcome to the {} form of string formatting".format('str.format(...)')
'Hello reader, welcome to the str.format(...) form of string formatting'
>>>
>>> print("""Formatting multiple ({0}, {1}, {2}, ...) values requires  
... that you use multiple {3} brackets and optionally specify ordering
... values.""".format(1,2,3,'{}'))
Formatting multiple (1, 2, 3, ...) values requires  
that you use multiple {} brackets and optionally specify ordering
values.
>>>
>>> print("""The {language} str.format() method also allows you to use
... named parameters which help keep code {adjective}
... """.format(language='Python', adjective='concise'))
The Python str.format() method also allows you to use
named parameters which help keep code concise

Luego está la técnica string Template, que es una clase en el módulo de cadena. Este método de formateo de cadenas es un poco más detallado y no admite especificadores de tipo (s, d, f, etc...), a diferencia de los dos anteriores. Con esta técnica, usted especifica el marcador de posición en una cadena anteponiendo el valor deseado con un $ en el constructor de la clase Template(...), luego llama a un método substitute(...) en el objeto instanciado con un parámetro con nombre. Este método es mucho menos común debido a su potencia y flexibilidad reducidas.

1
2
3
4
>>> from string import Template
>>> tmpl = Template("Hello my name is $name")
>>> tmpl.substitute(name='Adam')
'Hello my name is Adam'

La última técnica, y la implementación más reciente que solo está disponible en Python 3.6, se conoce como interpolación de cadenas. Esto tiene similitudes con la cadena de plantilla de Javascript ES6. Las interpolaciones de cadenas requieren que el literal de la cadena tenga el prefijo f"" y permite que tanto las expresiones como las variables se especifiquen directamente dentro de la cadena siempre que estén rodeadas por corchetes {}.

1
2
3
4
5
6
>>> method="String Interpolation"
>>> f"Hello reader, I am the {method} of formatting"
'Hello reader, I am the String Interpolation of formatting'
>>>
>>> f"With this method you can have expressions like {{1 + 1}} = {1 + 1}"
'With this method you can have expressions like {1 + 1} = 2'

Profundizando en el formato de cadenas

En las siguientes secciones voy a restringir la discusión solo al método str.format() y la técnica de interpolación f"" ya que son los métodos preferidos para formatear cadenas. Los temas en los que me gustaría profundizar incluyen:

  1. Alineación de texto
  2. Formateo numérico
  3. Escriba conversiones

Tanto str.format() como las técnicas de interpolación comparten la misma sintaxis para definir el formato entre los corchetes {} que hacen uso de : para separar los identificadores ordinales o con nombre a la izquierda y las especificaciones de formato a la derecha .

Alineación de texto

Puede alinear valores dentro de una longitud específica de texto utilizando los símbolos <, > o ^ para especificar la alineación a la izquierda, la alineación a la derecha o el centrado, respectivamente. Luego, sigue esos símbolos con el ancho de carácter que desees.

Python > 2.6:

1
2
3
4
5
6
7
8
>>> left_aligned = "Left Align"
>>> center = "Centered"
>>> right_aligned = "Right Align"
>>> "{left_aligned:<15}{center:^10}{right_aligned:>15}".format(
...     left_aligned=left_aligned,
...     center=center,
...     right_aligned=right_aligned)
'Left Align      Centered     Right Align'

También puede especificar las posiciones ordinales en lugar de palabras clave.

1
2
>>> "{1:<15}{0:^10}{2:>15}".format(center, left_aligned, right_aligned)
'Left Align      Centered     Right Align'

O bien, puede omitirlos si el orden de los parámetros para format(...) es el mismo orden que {}.

1
2
>>> "{:<15}{:^10}{:>15}".format(left_aligned, center, right_aligned)
'Left Align      Centered     Right Align'

python 3.6:

1
2
>>> f"{left_aligned:<15}{center:^10}{right_aligned:>15}"
'Left Align      Centered     Right Align'

En los ejemplos anteriores, llené implícitamente el espacio acolchado restante con espacios en blanco, que es el comportamiento predeterminado. Sin embargo, si esto no es lo que desea, puede llenarlos con algo diferente especificando un carácter inmediatamente después de los dos puntos.

Python > 2.6:

1
2
>>> "{:><15}|{:-^10}|{:<>15}".format(left_aligned, center, right_aligned)
'Left Align>>>>>|-Centered-|<<<<Right Align'

python 3.6:

1
2
>>> f"{left_aligned:><15}{center:-^10}{right_aligned:<>15}"
'Left Align>>>>>-Centered-<<<<Right Align'

Números

Formatear números de punto flotante, aquellos que contienen lugares decimales, es pan comido en Python. Todo lo que necesitas hacer es seguir los dos puntos con una f.

Python > 2.6:

1
2
3
>>> rounded_pi = 3.14
>>> "A rounded representation of Pi {:f}".format(rounded_pi)
'A rounded representation of Pi 3.140000'

python 3.6:

1
2
>>> f"A rounded representation of Pi {rounded_pi:f}"
'A rounded representation of Pi 3.140000'

Observe que la cadena tiene seis lugares decimales. Esto se debe a que, de manera predeterminada, el especificador flotante tiene seis lugares que llenará con ceros o los redondeará para que solo contengan seis, según la entrada. Por ejemplo, si importo la constante pi más larga del módulo matemático, verá el redondeo en acción.

Python > 2.6:

1
2
3
4
5
>>> from math import pi
>>> pi
3.141592653589793
>>> "A rounded representation of Pi {:f}".format(pi)
'A rounded representation of Pi 3.141593'

python 3.6:

1
2
>>> f"A rounded representation of Pi {pi:f}"
'A rounded representation of Pi 3.141593'

Para especificar una precisión diferente (número de lugares decimales), simplemente preceda la f por el número de lugares decimales deseados de esta manera.

Python > 2.6:

1
2
>>> "A rounded representation of Pi {:.3f}".format(pi)
'A rounded representation of Pi 3.142'

python 3.6:

1
2
>>> f"A rounded representation of Pi {pi:.3f}"
'A rounded representation of Pi 3.142'

Otro caso de uso de formato para números de coma flotante es el especificador de porcentaje. Esto funciona convirtiendo lo que se espera que sea una proporción o razón (0-1) en un valor de 100 y trata la parte decimal sobrante de forma similar al especificador f con una precisión predeterminada de seis.

Python > 2.6:

1
2
3
4
>>> receptions = 17
>>> passes = 29
>>> "The completion percentage is {:.2%}".format(receptions/passes)
'The completion percentage is 58.62%'

python 3.6:

1
2
>>> f"The completion percentage is {receptions/passes:.2%}"
'The completion percentage is 58.62%'

Bien, eso se ocupa de la mayoría de los casos de uso que involucran números de punto flotante, pero ¿qué pasa con los números grandes? Python también tiene soporte para formatearlos poniendo comas para aumentar la legibilidad de números grandes. Para aprovechar esto, simplemente coloque un , después de los dos puntos.

Python > 2.6:

1
2
3
>>> house_price = 299999.99
>>> "The price of the house is ${:,}".format(house_price)
'The price of the house is $299,999.99'

python 3.6:

1
2
>>> f"The price of the house is ${house_price:,}"
'The price of the house is $299,999.99'

Conversiones de tipo

Las conversiones de tipo son un caso de uso un poco menos común, pero surgen de vez en cuando. Las principales conversiones de tipo son las siguientes para números:

Descripción de la conversión


b Binario o Octal x hexadecimal decimales

Al igual que con los otros especificadores de formato, funcionan agregándolos después de los dos puntos. Con suerte, este patrón general de formato de sintaxis se vuelve claro para usted.

Python > 2.6:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
>>> number = 157
>>> print("Binary: {:b}\nOctal {:o}\nHexadecimal: {:x}\nDecimal: {:d}".format(
...     number,
...     number,
...     number,
...     number))
Binary: 10011101
Octal 235
Hexadecimal: 9d
Decimal: 157

python 3.6:

1
2
3
4
5
>>> print(f"Binary: {number:b}\nOctal {number:o}\nHexadecimal: {number:x}\nDecimal: {number:d}")
Binary: 10011101
Octal 235
Hexadecimal: 9d
Decimal: 157

Conclusión

En este breve tutorial sobre el formato de cadenas, apenas he arañado la superficie, pero espero haber podido dar algunos ejemplos concretos de casos de uso comunes con los que es probable que se encuentre en sus programas de Python del día a día. Mi objetivo ha sido proporcionar una explicación básica de la sintaxis de formato de cadena y las técnicas de implementación. A partir de aquí, debe estar armado con suficiente comprensión para profundizar en los detalles de la documentación. Gracias por leer y siéntase libre de comentar a continuación.

Licensed under CC BY-NC-SA 4.0