37- String Formatting en Python




Lección: [Número de Lección] - [Título de la Lección]

✨ String Formatting

El formateo de cadenas es una de las operaciones más comunes en la programación. Permite insertar valores de variables dentro de cadenas de texto de manera legible y controlada. Python ofrece varias formas de realizar el formateo de cadenas, cada una con sus propias ventajas y sintaxis.

Históricamente, Python ha tenido diferentes métodos para formatear cadenas:

  • Concatenación con el operador `+`: Aunque simple para casos básicos, puede volverse engorroso y menos legible cuando se combinan muchos valores o diferentes tipos de datos.
  • Formateo con el operador `%`: Un método más antiguo inspirado en la función printf de C.
  • El método `.format()`: Introducido en Python 2.6, ofrece una forma más potente y flexible de formatear cadenas.
  • F-strings (String Literals con formato): Introducidas en Python 3.6, proporcionan una sintaxis concisa y legible para incrustar expresiones dentro de cadenas.

En esta lección, exploraremos principalmente las formas más modernas y recomendadas de formatear cadenas: f-strings y el método `.format()`. También mencionaremos brevemente los placeholders con el operador `%` por su presencia en código más antiguo.

¿Por qué es importante el formateo de cadenas?

  • Legibilidad: Facilita la creación de cadenas que incluyen valores dinámicos de manera clara.
  • Control de formato: Permite especificar cómo se deben mostrar los valores (ej. número de decimales, alineación, etc.).
  • Eficiencia: Los métodos modernos de formateo suelen ser más eficientes que la concatenación repetida de cadenas.

En los siguientes temas, profundizaremos en cada uno de estos métodos, comenzando por la forma más moderna y ampliamente utilizada: las f-strings.

⭐ F-Strings

Las f-strings, también conocidas como "formatted string literals", son una de las formas más elegantes y legibles de formatear cadenas en Python, introducidas en la versión 3.6. Permiten incrustar expresiones dentro de cadenas de texto directamente, precediendo la cadena con una `f` o `F`.

Sintaxis básica de las f-strings:

                    nombre = "Ana"
edad = 30
saludo = f"Hola, mi nombre es {nombre} y tengo {edad} años."
print(saludo)
                    
                

En este ejemplo, las variables nombre y edad se insertan directamente dentro de la cadena literal al estar encerradas entre llaves `{}`. Python evalúa las expresiones dentro de las llaves y las reemplaza con sus valores.

Insertando expresiones:

Dentro de las llaves de una f-string, puedes incluir no solo nombres de variables, sino también cualquier expresión válida de Python:

                    x = 10
y = 5
print(f"La suma de {x} y {y} es {x + y}.")
print(f"El doble de {x} es {x * 2}.")
                    
                

Python calculará la suma y la multiplicación directamente dentro de la f-string.

Llamando a funciones:

También puedes llamar a funciones dentro de las llaves de una f-string:

                    def saludar(nombre):
    return f"¡Saludos, {nombre}!"

nombre_usuario = "Carlos"
mensaje = f"{saludar(nombre_usuario)}"
print(mensaje)
                    
                

La función saludar se ejecuta y su valor de retorno se inserta en la f-string.

Las f-strings ofrecen una sintaxis muy concisa y legible para el formateo de cadenas, lo que las convierte en la opción preferida para muchas tareas en Python moderno.

⚙️ Placeholders and Modifiers

✨ En las f-strings, los placeholders son las expresiones que colocamos dentro de las llaves `{}`. Además de simplemente insertar el valor de una variable, podemos usar modificadores dentro de estos placeholders para controlar cómo se formatea ese valor.

Formato básico:

Ya hemos visto el formato básico donde simplemente colocamos el nombre de la variable dentro de las llaves: f"El valor es {variable}".

Especificando el formato:

Para añadir modificadores, utilizamos dos puntos `:` después de la expresión dentro de las llaves, seguido de la especificación del formato.

Ejemplo: Formateando números con decimales

                    pi = 3.14159
print(f"El valor de pi con dos decimales es: {pi:.2f}")
                    
                

Aquí, :.2f es el modificador que indica que queremos formatear la variable pi como un número de punto flotante con dos decimales.

Ejemplo: Formateando números enteros con separadores de miles

                    cantidad = 1234567
print(f"La cantidad con separadores de miles es: {cantidad:,}")
                    
                

El modificador `,` añade separadores de miles (dependiendo de la configuración regional).

Ejemplo: Formateando en diferentes bases numéricas

                    numero = 255
print(f"En binario: {numero:b}")
print(f"En hexadecimal (minúsculas): {numero:x}")
print(f"En hexadecimal (mayúsculas): {numero:X}")
print(f"En octal: {numero:o}")
                    
                

Los modificadores b, x, X y o permiten formatear enteros en binario, hexadecimal (minúsculas), hexadecimal (mayúsculas) y octal, respectivamente.

Estos son solo algunos ejemplos de los modificadores que se pueden utilizar dentro de los placeholders de las f-strings. Ofrecen un gran control sobre cómo se presentan los datos dentro de las cadenas formateadas.

💡 Perform Operations in F-Strings

💡 Una de las características poderosas de las f-strings es que permiten realizar operaciones directamente dentro de los placeholders `{}`. Esto significa que no necesitas calcular un valor en una línea separada y luego insertarlo; puedes hacerlo directamente en la cadena formateada.

Operaciones aritméticas:

Puedes realizar operaciones aritméticas básicas directamente dentro de las llaves:

                    a = 5
b = 10
print(f"La suma de {a} y {b} es {a + b}.")
print(f"La diferencia entre {b} y {a} es {b - a}.")
print(f"El producto de {a} por {b} es {a * b}.")
print(f"La división de {b} entre {a} es {b / a}.")
                    
                

Python evaluará estas expresiones y mostrará los resultados dentro de la cadena.

Comparaciones:

También puedes realizar comparaciones lógicas dentro de las f-strings, aunque el resultado será un valor booleano (True o False), que quizás no siempre sea lo que quieres mostrar directamente en la cadena formateada. Sin embargo, puede ser útil en expresiones más complejas.

                    edad = 25
print(f"¿Es mayor de 18? {edad > 18}")
                    
                

Acceso a elementos de colecciones:

Puedes acceder a elementos de listas, tuplas o diccionarios directamente dentro de las f-strings utilizando sus índices o claves:

                    mi_lista = [10, 20, 30]
mi_diccionario = {"nombre": "Juan", "ciudad": "Madrid"}
print(f"El primer elemento de la lista es: {mi_lista[0]}.")
print(f"El nombre en el diccionario es: {mi_diccionario['nombre']}.")
                    
                

Realizar operaciones directamente en las f-strings puede hacer que tu código sea más conciso y legible en muchos casos, evitando la necesidad de variables intermedias para almacenar resultados de operaciones simples.

📞 Execute Functions in F-Strings

📞 Las f-strings no solo permiten insertar variables y realizar operaciones básicas, sino que también te brindan la flexibilidad de ejecutar funciones directamente dentro de los placeholders `{}`. Esto puede simplificar significativamente tu código al realizar transformaciones o obtener valores dinámicamente en el momento del formateo.

Llamando a funciones definidas por el usuario:

Puedes llamar a cualquier función que hayas definido previamente en tu código:

                    def obtener_nombre_completo(nombre, apellido):
    return f"{nombre} {apellido}"

nombre = "Laura"
apellido = "Gómez"
print(f"El nombre completo es: {obtener_nombre_completo(nombre, apellido)}.")
                    
                

Aquí, la función obtener_nombre_completo se llama dentro de la f-string, y su valor de retorno se inserta en la cadena.

Llamando a métodos de objetos:

También puedes invocar métodos en objetos dentro de las f-strings:

                    texto = "hola mundo"
print(f"El texto en mayúsculas es: {texto.upper()}.")
print(f"¿El texto comienza con 'hola'? {texto.startswith('hola')}.")
                    
                

Los métodos upper() y startswith() del objeto string texto se ejecutan dentro de la f-string.

Usando funciones incorporadas de Python:

Puedes llamar a funciones built-in de Python como len(), str(), int(), etc.:

                    mi_lista = [1, 2, 3, 4, 5]
print(f"La longitud de la lista es: {len(mi_lista)}.")
numero = 123
print(f"El número como cadena es: {str(numero)}.")
                    
                

La capacidad de ejecutar funciones directamente en f-strings proporciona una forma concisa y poderosa de formatear cadenas con valores que requieren algún tipo de procesamiento o transformación en el momento de la inserción.

🎨 More Modifiers

🎨 Además de los modificadores básicos para formatear números y bases, las f-strings ofrecen una variedad de modificadores adicionales para controlar la alineación, el relleno, el signo de los números y más.

Alineación y relleno:

Puedes controlar cómo se alinea el valor dentro de un cierto ancho de campo y especificar un carácter de relleno si es necesario.

  • :<ancho: Alinea a la izquierda dentro del ancho especificado.
  • :>ancho: Alinea a la derecha dentro del ancho especificado.
  • :^ancho: Centra dentro del ancho especificado.
  • :relleno<ancho, :relleno>ancho, :relleno^ancho: Utiliza el carácter `relleno` para completar el espacio hasta el `ancho` especificado.
                    texto = "Python"
numero = 123
print(f"'{texto:<10}'")   # Alinea a la izquierda en 10 caracteres
print(f"'{texto:>10}'")   # Alinea a la derecha en 10 caracteres
print(f"'{texto:^10}'")   # Centra en 10 caracteres
print(f"'{numero:0>5}'")  # Rellena con ceros a la izquierda hasta 5 dígitos
print(f"'{numero:*^7}'")  # Centra y rellena con asteriscos hasta 7 caracteres
                    
                

Signo de los números:

Puedes controlar cómo se muestra el signo de los números positivos y negativos.

  • :+: Muestra el signo para números positivos y negativos.
  • :-: Muestra el signo solo para números negativos (comportamiento predeterminado).
  • : (un espacio): Muestra un espacio para números positivos y el signo menos para los negativos.
                    positivo = 42
negativo = -42
print(f"Positivo con signo: {positivo:+}")
print(f"Negativo con signo: {negativo:+}")
print(f"Positivo con espacio: {positivo: }")
print(f"Negativo con espacio: {negativo: }")
                    
                

Otros modificadores útiles:

  • :,: Separador de miles (ya visto).
  • :.precisiónf: Formato de punto flotante con la precisión especificada (ya visto).
  • :.precióng: Formato general. Utiliza notación de punto fijo para números pequeños y notación científica para números grandes. La precisión indica el número de dígitos significativos.
  • :%: Formatea el número como un porcentaje (multiplica por 100 y añade el signo %).
                    numero_grande = 1234567.89
porcentaje = 0.75
print(f"Número grande con formato general (3 dígitos significativos): {numero_grande:.3g}")
print(f"Porcentaje: {porcentaje:.2%}")
                    
                

Estos modificadores adicionales proporcionan un control aún mayor sobre la presentación de tus datos al formatear cadenas con f-strings, permitiéndote generar salidas bien estructuradas y fáciles de leer.

🔗 String format()

🔗 El método .format() es otra forma poderosa y flexible de formatear cadenas en Python, introducida en Python 2.6. Permite crear cadenas formateadas utilizando placeholders dentro de la cadena y luego pasando los valores a insertar como argumentos del método .format().

Sintaxis básica:

                    nombre = "Ricardo"
edad = 35
saludo = "Hola, mi nombre es {} y tengo {} años.".format(nombre, edad)
print(saludo)
                    
                

En este ejemplo, las llaves `{}` actúan como placeholders. Los valores pasados al método .format() se insertan en estos placeholders en el orden en que se proporcionan.

Placeholders con índices:

Puedes referirte a los argumentos del método .format() por su índice (posición):

                    nombre = "Sofía"
edad = 28
saludo = "Hola, mi nombre es {0} y tengo {1} años. {0} es un nombre bonito.".format(nombre, edad)
print(saludo)
                    
                

Aquí, {0} se refiere al primer argumento (nombre) y {1} al segundo (edad). Esto permite reutilizar los argumentos.

Placeholders con nombres:

También puedes asignar nombres a los argumentos en el método .format() y referirte a ellos por esos nombres en los placeholders:

                    datos = {"nombre": "Javier", "edad": 40}
saludo = "Hola, mi nombre es {nombre} y tengo {edad} años.".format(**datos)
print(saludo)

# O directamente:
saludo2 = "Hola, mi nombre es {nombre} y tengo {edad} años.".format(nombre="Elena", edad=32)
print(saludo2)
                    
                

Usar nombres puede mejorar la legibilidad, especialmente cuando hay muchos valores a formatear.

Especificando el formato (modifiers):

Al igual que con las f-strings, puedes usar modificadores después de los dos puntos `:` dentro de los placeholders para controlar el formato de los valores:

                    pi = 3.14159
print("El valor de pi con dos decimales es: {:.2f}".format(pi))
cantidad = 1234567
print("La cantidad con separadores de miles es: {:,}".format(cantidad))
                    
                

La sintaxis de los modificadores es similar a la de las f-strings.

El método .format() sigue siendo una herramienta valiosa para el formateo de cadenas, especialmente en versiones de Python anteriores a la 3.6 o en casos donde la claridad de nombrar los placeholders es preferible.

🔢 Multiple Values

🔢 El método .format() se vuelve especialmente útil cuando necesitas insertar múltiples valores en una cadena. Ya hemos visto ejemplos básicos, pero aquí exploraremos cómo trabajar con colecciones de datos y cómo referirnos a sus elementos dentro de la cadena formateada.

Insertando elementos de listas y tuplas:

Puedes acceder a los elementos de listas o tuplas utilizando índices dentro de los placeholders:

                    datos_lista = ["Manzana", 2.50, 10]
mensaje_lista = "La {0} cuesta ${1:.2f} y hay {2} en stock.".format(*datos_lista)
print(mensaje_lista)

datos_tupla = ("Carlos", "Pérez")
mensaje_tupla = "El nombre es {0} y el apellido es {1}.".format(*datos_tupla)
print(mensaje_tupla)
                    
                

El operador `*` se utiliza para desempaquetar los elementos de la lista o tupla y pasarlos como argumentos posicionales a .format().

Insertando valores de diccionarios:

Puedes insertar valores de diccionarios utilizando las claves como nombres en los placeholders o desempaquetando el diccionario con **:

                    datos_diccionario = {"nombre": "Ana", "edad": 30, "ciudad": "Sevilla"}
mensaje_diccionario = "Nombre: {nombre}, Edad: {edad}, Ciudad: {ciudad}.".format(**datos_diccionario)
print(mensaje_diccionario)

# También puedes acceder a los valores directamente usando índices de las claves:
mensaje_diccionario_indice = "Nombre: {0[nombre]}, Edad: {0[edad]}, Ciudad: {0[ciudad]}.".format(datos_diccionario)
print(mensaje_diccionario_indice)
                    
                

Al usar **datos_diccionario, los pares clave-valor del diccionario se pasan como argumentos nombrados a .format().

Combinando diferentes tipos de valores:

Puedes combinar argumentos posicionales, argumentos por nombre y acceso a elementos de colecciones en una misma llamada a .format():

                    nombre = "Luis"
puntuacion = 95
materias = ["Matemáticas", "Ciencias"]
datos_extra = {"profesor": "Martínez"}

mensaje_combinado = "El estudiante {0} obtuvo {1} en {2[0]} (profesor: {extra[profesor]}).".format(nombre, puntuacion, materias, extra=datos_extra)
print(mensaje_combinado)
                    
                

Este ejemplo muestra cómo se pueden mezclar diferentes formas de referirse a los valores.

El método .format() proporciona una gran flexibilidad para trabajar con múltiples valores de diversas fuentes al formatear cadenas.

#️⃣ Index Numbers

#️⃣ Como vimos brevemente en un tema anterior, el método .format() permite utilizar números de índice dentro de los placeholders `{}` para referirse a los argumentos pasados al método. Esto proporciona un control explícito sobre qué valor se inserta en cada posición de la cadena.

Referencia posicional explícita:

Al colocar un número entero dentro de las llaves, estás indicando que quieres insertar el argumento que se encuentra en esa posición (indexado desde 0) en la llamada a .format().

                    nombre = "Alicia"
edad = 22
ciudad = "Barcelona"
mensaje = "Mi nombre es {0}, tengo {1} años y vivo en {2}.".format(nombre, edad, ciudad)
print(mensaje)
                    
                

Aquí, {0} se reemplaza con nombre, {1} con edad y {2} con ciudad.

Reutilización de argumentos:

Una de las ventajas de usar números de índice es que puedes referirte al mismo argumento varias veces dentro de la cadena formateada:

                    nombre = "Pedro"
mensaje_repetido = "{0}, ¡qué gran nombre {0}!".format(nombre)
print(mensaje_repetido)

coordenadas = (10, 20)
mensaje_coordenadas = "La coordenada x es {0[0]} y la coordenada y es {0[1]}.".format(coordenadas)
print(mensaje_coordenadas)
                    
                

En el primer ejemplo, {0} (que representa "Pedro") se utiliza dos veces. En el segundo, {0} se refiere a la tupla coordenadas, y luego accedemos a sus elementos usando índices dentro de las llaves.

Combinando índices con formato:

Puedes combinar el uso de índices con los especificadores de formato:

                    precio = 45.678
mensaje_precio = "El precio es {0:.2f} euros.".format(precio)
print(mensaje_precio)
                    
                

Aquí, {0:.2f} indica que se debe usar el primer argumento (precio) y formatearlo como un número de punto flotante con dos decimales.

El uso de números de índice en .format() proporciona una manera clara y a veces más concisa de referirse a los valores, especialmente cuando se reutilizan o cuando el orden de los argumentos es importante.

🏷️ Named Indexes

🏷️ Además de referirte a los argumentos de .format() por su posición (índice numérico), también puedes referirte a ellos por nombres. Esto puede mejorar significativamente la legibilidad del código, especialmente cuando hay muchos valores a insertar o cuando el orden de los argumentos no es intuitivo.

Pasando argumentos por nombre:

Al llamar al método .format(), puedes asignar nombres a los argumentos utilizando la sintaxis nombre_argumento=valor. Luego, puedes usar estos nombres dentro de los placeholders de la cadena.

                    mensaje = "El nombre es {nombre} y la edad es {edad}.".format(nombre="Carmen", edad=28)
print(mensaje)
                    
                

Aquí, los valores "Carmen" y 28 se pasan con los nombres "nombre" y "edad", respectivamente, que luego se utilizan en los placeholders.

Usando diccionarios para argumentos con nombre:

Como vimos anteriormente, puedes usar el desempaquetado de diccionarios (**) para pasar múltiples argumentos con nombre a .format():

                    persona = {"nombre": "Miguel", "profesion": "Ingeniero"}
saludo = "Hola, {nombre}. ¿Cómo va tu trabajo como {profesion}?".format(**persona)
print(saludo)
                    
                

Las claves del diccionario se utilizan como nombres de los argumentos en .format().

Combinando argumentos posicionales y con nombre:

Es posible combinar argumentos posicionales y con nombre en la misma llamada a .format(), aunque generalmente se recomienda usar uno u otro para mayor claridad.

                    mensaje_combinado = "El valor en la posición 0 es {0} y el nombre es {nombre}.".format(100, nombre="Sofía")
print(mensaje_combinado)
                    
                

En este caso, {0} se refiere al primer argumento posicional (100), y {nombre} al argumento con nombre "nombre" ("Sofía").

El uso de nombres en los placeholders de .format() a menudo conduce a un código más legible y mantenible, ya que el significado de cada valor insertado es explícito en la cadena de formato.




Publicar un comentario

0 Comentarios