Formatear cadenas con Python

F

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 pesado, pero la necesidad de tener una representación de cadena específica sigue siendo un caso de uso bastante común. Mi primera introducció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 el printf(...) función. Una cosa que se mantuvo así entonces y que todavía lo es ahora es que la documentación para el formateo de cadenas (prácticamente para todos los idiomas) deja mucho que desear. Espero aliviar este dolor hoy escribiendo sobre cómo lograr el formateo de cadenas en Python.

En Python hay varias 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 lenguaje, probablemente haya visto esta variedad de técnicas dispares y se haya preguntado, “¿cuál es el problema con todo esto?”.

Revisión de las técnicas de formato de cuatro cadenas

Comencemos con el método más común que utiliza 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, Stack Overflow, etc.). Para utilizar este método, especifica un marcador de posición en una cadena usando %s para Strings y %d para los números.

>>> "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 la str.format(...) método. Este estaba destinado a ser el reemplazo de la % estilo mostrado anteriormente. Esta técnica utiliza las llaves {} designador para especificar dónde y cómo formatear un valor en una cadena.

>>> "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 de la plantilla de cadena, que es una clase en el módulo de String. 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, especifica el marcador de posición en una cadena prefijando el valor deseado con un $ en el constructor del Template(...) clase, luego llamas a un substitute(...) en el objeto instanciado con un parámetro con nombre. Este método es mucho menos común debido a su menor potencia y flexibilidad.

>>> 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 Strings. Esto tiene similitudes con la cadena de plantilla Javascript ES6. Las interpolaciones de cadenas requieren que el literal de cadena tenga un prefijo f"" y permite que tanto las expresiones como las variables se especifiquen directamente dentro de la cadena siempre que estén rodeadas por {} soportes.

>>> 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 a los str.format() método y f"" técnica de interpolación, ya que son los métodos preferidos para formatear cadenas. Los temas en los que me gustaría profundizar incluyen:

  • Alineación del texto
  • Formateo de números
  • Conversiones de tipos

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

Alineación del texto

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

Python> 2.6:

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

O puede omitirlos si el orden de los parámetros para format(...) son del mismo orden del {}.

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

Python 3.6:

>>> 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 completarlos con algo diferente especificando un carácter inmediatamente después de los dos puntos.

Python> 2.6:

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

Python 3.6:

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

Números

Dar formato a números de coma flotante, aquellos que contienen posiciones decimales, es pan comido en Python. Todo lo que necesita hacer es seguir los dos puntos con un f.

Python> 2.6:

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

Python 3.6:

>>> 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 forma predeterminada, el especificador flotante tiene seis lugares que rellenará con ceros o redondeará para contener solo 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:

>>> 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:

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

Para especificar una precisión diferente (número de posiciones decimales) simplemente preceda al f por el número de lugares decimales deseado como tal.

Python> 2.6:

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

Python 3.6:

>>> 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 punto flotante es el especificador de porcentaje. Esto funciona convirtiendo lo que se espera que sea una proporción o razón (0-1) a un valor de 100 y trata la porción decimal sobrante de manera similar a la f especificador con una precisión predeterminada de seis.

Python> 2.6:

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

Python 3.6:

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

Ok, 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 colocando comas para aumentar la legibilidad de números grandes. Para aprovechar esto, simplemente coloque un , después del colon.

Python> 2.6:

>>> 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:

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

Conversiones de tipo

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

Descripción de conversión

segundoBinario
oOctal
XHexadecimal
reDecimal

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 sintaxis de formato se está volviendo claro para usted.

Python> 2.6:

>>> 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:

>>> 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 diarios de Python. Mi objetivo ha sido proporcionar una explicación básica de la sintaxis del formato de cadenas y las técnicas de implementación. A partir de aquí, debe tener la suficiente comprensión para profundizar en los detalles de la documentación. Gracias por leer y comentar a continuación.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad