Formateo de cadenas en Python
CategoriasProgramaciónPython

Formateo de cadenas en Python

Formateo de cadenas

En Python, como en todos los lenguajes de programación, tenemos una u otra manera de formatear cadenas.

El formateo de cadenas no es otra cosa que insertar valores dentro de una cadena de texto usando métodos como la concatenación, operadores u otro método específico del propio lenguaje. Esto nos permite crear mensajes dinámicos o personalizados. Creo que ya todo el mundo lo sabemos, sin embargo, lo que a lo mejor desconocemos es que en Python, hoy en día conviven o existen tres maneras de hacerlo. ¡Si, tres!

Antiguamente, es decir, en las primeras versiones de Python y permíteme la expresión “casi toda la vida”, se ha usado el “formateo estilo printf”, es decir, se utiliza el operador módulo (%) o también llamado operador de cadena, para insertar valores dentro de una cadena.

Por ejemplo:

# Estilo printf
print("%s tiene %d años" % ("Óscar", 36))

Más tarde, en versiones más nuevas de Python (creo que a partir de la 2.6) se implementó el método str.format() para formatear cadenas.

# Usando str.format()
print("{} tiene {} años".format("Óscar", 36))

Y ya, por último, concretamente a partir de la versión 3.6 se usa lo que se llama f-strings para el formateo de cadenas.

# F-string
name = "Óscar"
age = 36
print(f"{name} tiene {age} años.")

Veamos uno por uno.

Estilo printf u operador %

Como he comentado al principio, el “formateo estilo printf” es el método más antiguo debido a que se usaba (y aun se puede usar, aunque bastante menos) desde el principio de Python. Se llama así porque está inspirado en la función printf (print formatted) del lenguaje C.

Esta función se usa para imprimir texto con formato utilizando los tipos de conversión como %s (para cadena), %d (número entero), %f (número decimal), etc.

Como hemos visto en el ejemplo del principio, no tiene ningún misterio. Se trata de escribir una cadena y, dentro de la cadena el tipo de conversión adecuado para después escribir el operador % seguido del valor que le queremos dar.

Habíamos visto un ejemplo, pero veamos otro.

print("El blog de %s es el mejor!" % "Óscar")

print("El valor de pi es %f" % 3.14)

O perfeccionándolo un poco más:

pi = 3.14
print("El valor de pi con 2 decimales es %.2f" % pi)

Al usar “%f” representamos números de coma flotante, y al usarlo con “%.2f” le indicamos que nos muestre solo dos decimales.

¿Sencillo no?

Ahora bien, este modo de formateo de cadenas ya está en desuso debido a que es menos flexible y menos legible a los otros.

Uno de los principales inconvenientes es que tienes que asegurarte de que el número y tipo de los valores que proporcionas coincidan exactamente con los marcadores % en la cadena.

Por ejemplo:

name = "Óscar"
age = 36
print("Mi nombre es %s y tengo %d años." % (name, age))

También, si queremos usar el nombre en dos lugares, tenemos que repetirlo manualmente en la tupla:

print("%s es mi nombre y %s es mi nombre otra vez." % (name, name))

Cosa que no sucede con los otros métodos como veremos más adelante.

Otro inconveniente es la lectura. Mira la siguiente línea:

print("El trabajador %s tiene %d años, vive en %s, y recibe un sueldo de %.2f euros." % ("Óscar", 36, "La quinta avenida", 2050.49))

¿Qué poco legible no? Esto dificulta saber qué valor corresponde con cada marcador (%s, %d, %s, %.2f).

Por último, si le pasas un dato que no coincide con el tipo esperado dará error, cosa que una vez más con los otros métodos no hay problema.

name = "Óscar"
age = "36"
print("Mi nombre es %s y tengo %d años." % (name, age))

Nos lanza el error: TypeError: %d format: a real number is required, not str

Por todo esto, es por lo que el operador % para el formateo de cadenas quedó en desuso por otros métodos o técnicas más modernas.

La siguiente evolución fue el método “str.format()”.

Método str.format()

Este método, a diferencia del anterior, es mucho más flexible y legible. Utiliza las llaves ({}) llamadas marcadores, dentro de la cadena, que luego se reemplazan con los valores pasados como argumentos al método.

Con este método se pueden usar índices, nombres clave o simplemente dejar los marcadores vacíos.

Por ejemplo:

print("{} tiene {} años".format("Óscar", 36))
name = "Óscar"
age = 36
print("{} tiene {} años.".format(name, age))

Como he dicho, también podemos usar índices. Siendo útil si necesitas usar el mismo valor varias veces sin repetirlo. Cosa que con el operador módulo estábamos obligados a repetir el mismo nombre en la tupla. ¿Lo recuerdas?

print("{0} es un {1} que personalmente me encanta. {0} es {2}!.".format("Python", "lenguaje", "poderoso"))

La salida es: “Python es un lenguaje que personalmente me encanta. Python es poderoso!”

También podemos usar nombres clave para los valores:

print("La {insecto} tiene {patas} patas.".format(insecto="mariposa", patas=6))

Salida: “La mariposa tiene 6 patas.”

Evidentemente también podemos aplicar algún formato específico para por ejemplo con los números decimales:

pi = 3.14159265359
print("El valor de pi es {:.2f}".format(pi))

Salida: “El valor de pi es 3.14”.

También se puede usar un diccionario descomponiendo (usando la sintaxis **) sus valores e insertándolos en la cadena.

datos = {"nombre": "Óscar", "edad": 36, "pais": "España"}
print("Hola, mi nombre es {nombre}, tengo {edad} años y vivo en {pais}.".format(**datos))

Salida: “Hola, mi nombre es Óscar, tengo 36 años y vivo en España.”

Y oye, también podemos usar algo de lógica. Mira el siguiente ejemplo:

productos = 3
plural = "s" if productos > 1 else ""

print("Tienes en la cesta {} producto{}.".format(productos, plural))

Dependiendo de la cantidad de productos la salida será:

“Tienes en la cesta 3 productos.”

O bien:

“Tienes en la cesta 1 producto.”

¿Ves la diferencia y una vez más la potencia de Python? 😊

Como ves el método str.format() es bastante potente, flexible y legible y claro está, que mejora mucho respecto a su predecesor (al formateo estilo printf).

Las f-strings

Las f-strings son una evolución del método str.format() introducida en Python 3.6 que permite, como todos los anteriores métodos que hemos visto, formatear cadenas pero de manera más eficiente y legible gracias a una sintaxis más concisa. Actualmente es el estándar para formatear cadenas en Python y nos permite usar tanto variables, como expresiones directamente dentro de la cadena.

Al igual que str.format(), hace uso de llaves {} para colocar dentro de ella las variables o expresiones.

Por ejemplo, una cadena típica es la siguiente:

print("Hola, me llamo Óscar")

Pues bien, la sintaxis de f-strings es utilizar el prefijo f o F antes de las comillas de la cadena y las variables o expresiones colocarlas dentro de las llaves.

Por ejemplo:

name = "Óscar"
age = 36
print(f"{name} tiene {age} años.")

Aquí ya vemos una diferencia importante respecto al método str.format(). Como ves, las f-strings, acceden directamente a las variables del contexto, mientras que str.format() requiere pasar las variables como argumentos a través del método format().

name = "Óscar"
age = 36
print("{} tiene {} años.".format(name, age))

Otra ventaja y potencia de las f-strings, es que nos permite usar expresiones, porque al igual que las variables son reemplazadas por sus correspondientes valores, las expresiones son reemplazadas por el correspondiente resultado que da la operación. Esto nos hace pensar que también podríamos usar funciones dentro de las f-string, ya que entendemos que la función será reemplazada por el valor correspondiente que retorna la función, ¿no? ¡Pues sí, asi es! 😉

Veamos algunos ejemplos.

Vamos a sumar dos números:

a = 10
b = 5
print(f"La suma de {a} y {b} es: {a + b}")

Como ves calculamos la suma directamente dentro de la cadena, cosa que con str.format() deberíamos de hacer:

a = 10
b = 5
print("La suma de {} y {} es: {}".format(a, b, a + b))

Pero como dije antes, también podemos usar funciones, llamar a métodos de Python, usar diccionarios e incluso usar sentencias condicionales.

Por ejemplo, podemos hacer uso de un diccionario:

datos = {"nombre": "Óscar", "edad": 36, "pais": "España"}
print(f"Hola, mi nombre es {datos['nombre']}, tengo {datos['edad']} años y vivo en {datos['pais']}.")

O bien también, podemos usar nuestras propias funciones:

a = 10
b = 5
print(f"La suma de {a} y {b} es: {calcular_suma(a, b)}")

También podemos usar métodos propios de las cadenas de Python:

name = "óscar"
age = 36
country = "españa"
print(f"{name.upper()} tiene {age} años y vive en {country.capitalize()}")

Salida: “ÓSCAR tiene 36 años y vive en España”

Por otro lado, podemos usar join() dentro de una f-string para iterar y acceder a los elementos de un diccionario:

datos = {"nombre": "Óscar", "edad": 36, "pais": "España"}
print(f"Información:\n {' | '.join([f'{k}: {v}' for k, v in datos.items()])}")

Cuya salida será:

Información:

nombre: Óscar | edad: 36 | pais: España

Otra cosa más que podemos hacer, es usar condicionales dentro de la f-string:

age = 17
print(f"{'Puedes entrar' if age >= 18 else 'No puedes entrar'}")

Salida: “No puedes entrar”

num = 5
print(f"¿El número es par? {'Si' if num%2==0 else 'No'}")

Salida: “No”

Como has visto, en Python tenemos disponible tres maneras diferentes de formatear cadenas. Cada una tiene sus ventajas e inconvenientes como todo, claro está, sin embargo, hoy en día no creo que haya necesidad de usar el “estilo printf” (operador %) para formatear cadenas ya que las f-strings superan con creces a sus antecesores.

Las f-strings, aparte de ser el método estándar actual y de ser más sencillas, rápidas y claras, las hace extremadamente potentes y versátiles porque podemos trabajar con variables, diccionarios, funciones… y aplicar formateos avanzados de manera más directa y concisa.

¡Úsalas siempre! A no ser que por ejemplo busques compatibilidad con versiones anteriores a Python 3.6 y en ese caso, si que se recomendaría el uso del método str.format() por ejemplo.

Saludos!

Sobre el autor

Comparte:

Este artículo está publicado bajo una licencia Creative Commons Atribución-CompartirIgual 4.0 Internacional . Puedes compartirlo y adaptarlo, incluso con fines comerciales, siempre que cites al autor y mantengas esta misma licencia.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Información básica sobre protección de datos
Responsable Óscar Martínez +info...
Finalidad Gestionar y moderar los comentarios +info...
Legitimación Consentimiento del interesado. +info...
Destinatarios No se cederán datos a terceros, salvo obligación legal +info...
Derechos Acceder, rectificar y cancelar los datos, así como otros derechos. +info...
Información adicional Puedes consultar la información adicional y detallada sobre protección de datos en nuestra página de política de privacidad.

Este sitio esta protegido por reCAPTCHA y laPolítica de privacidady losTérminos del servicio de Googlese aplican.

El periodo de verificación de reCAPTCHA ha caducado. Por favor, recarga la página.