Formateo de Cadenas en Python
Aprende los tres métodos de formateo de cadenas en Python: operador %, str.format() y f-strings, con ejemplos de números, alineación, fechas y más.
El formateo de cadenas te permite construir string de forma dinámica insertando variables, expresiones y valores calculados en una plantilla. Python ofrece tres enfoques distintos: el operador % heredado, el versátil método str.format() y la moderna sintaxis de f-strings, cada uno con sus propias ventajas y casos de uso apropiados.
Este capítulo cubre:
- Cuándo usar cada método de formateo y por qué
- El operador
%(heredado, aún común en logs y bases de código antiguas) str.format()con marcadores de posición posicionales y con nombre- f-strings (el enfoque moderno recomendado)
- Especificadores de formato: ancho, alineación, precisión, relleno, signo y base
- Formateo de números, porcentajes, fechas y horas
- Errores comunes y casos especiales
Para una guía detallada sobre f-strings específicamente — incluyendo expresiones, lógica condicional y mejoras de Python 3.12 — consulta el capítulo Python f-Strings.
¿Qué Método Deberías Usar?
| Método | Versión de Python | Cuándo usarlo |
|---|---|---|
Operador % | 2.x / 3.x | Código heredado, módulo logging, sustituciones muy simples |
str.format() | 2.6+ | Cuando necesitas string de formato reutilizables o argumentos de palabra clave |
| f-strings | 3.6+ | Código nuevo — más rápido, más legible, admite expresiones en línea |
A menos que estés manteniendo código Python 2 o una base de código Python 3 antigua, usa f-strings. Se evalúan en tiempo de ejecución, no producen sobrecarga de llamadas adicional y mantienen el nombre de la variable junto al lugar donde aparece en la cadena.
El Operador % (Formateo Heredado)
El operador % sustituye valores en una string de formato usando especificadores de conversión de estilo C.
Especificadores de conversión comunes:
| Especificador | Significado |
|---|---|
%s | String (llama a str() sobre el valor) |
%d | Entero con signo |
%f | Número de punto flotante |
%r | repr() del valor |
%% | Un carácter % literal |
Ancho y Precisión con %
Puedes controlar el ancho de campo y la precisión decimal directamente en el especificador:
pi = 3.14159265
print("%10.3f" % pi) # right-aligned in a 10-char field, 3 decimal places
# 3.142
print("%-10.3f|" % pi) # left-aligned
# 3.142 |
print("%010.3f" % pi) # zero-padded
# 000003.142Error Común: Valores Únicos vs. Tuplas
Al sustituir un solo valor, pasar una tupla es el enfoque seguro:
value = "hello"
# Risky — if value were itself a tuple, this would fail:
# print("Got: %s" % value)
# Safe:
print("Got: %s" % (value,))
# Got: hellostr.format() — Formateo Flexible con Marcadores de Posición
El método str.format() reemplazó al operador % en Python 2.6+. Usa {} como marcadores de posición y admite argumentos posicionales, indexados y de palabra clave.
Marcadores de Posición Posicionales e Indexados
Marcadores de Posición con Nombre (Palabra Clave)
Los marcadores de posición con nombre hacen que las string de formato se documenten a sí mismas y son especialmente útiles cuando el mismo valor aparece varias veces o cuando la string de formato proviene de un archivo de configuración.
Reutilización de String de Formato
Dado que str.format() toma una string como entrada, puedes almacenar la plantilla en una variable y reutilizarla:
template = "Hello, {name}! You have {count} new messages."
print(template.format(name="Alice", count=3))
print(template.format(name="Bob", count=0))
# Hello, Alice! You have 3 new messages.
# Hello, Bob! You have 0 new messages.f-Strings — Formateo Moderno en Python
Las f-strings (literales de string formateadas) prefijan la string con f o F y evalúan cualquier expresión dentro de {} en tiempo de ejecución. Están disponibles desde Python 3.6 en adelante y son el enfoque recomendado para código nuevo.
name = "John"
age = 25
print(f"My name is {name} and I am {age} years old.")
# My name is John and I am 25 years old.Las f-strings admiten cualquier expresión Python válida dentro de las llaves: aritmética, llamadas a métodos, condicionales y más:
items = ["apple", "banana", "cherry"]
print(f"Cart has {len(items)} items. First: {items[0].upper()}.")
# Cart has 3 items. First: APPLE.
x = -7
print(f"Absolute value: {abs(x)}")
# Absolute value: 7Consulta Python f-Strings para la guía completa, incluyendo depuración con =, f-strings multilínea y mejoras de Python 3.12.
Especificadores de Formato: El Mini-Lenguaje
Tanto str.format() como las f-strings usan el mismo mini-lenguaje de especificación de formato dentro de {} después de los dos puntos:
{[field_name]:[fill][align][sign][#][0][width][grouping][.precision][type]}La siguiente tabla muestra las opciones más útiles:
| Opción | Carácter | Efecto |
|---|---|---|
| Alineación | < > ^ | Izquierda, derecha, centro |
| Relleno | cualquier carácter | Rellena el padding (se usa con alineación y ancho) |
| Signo | + - | Mostrar + para positivos; solo menos por defecto; espacio para positivos |
| Prefijo | # | 0x para hex, 0o para octal, 0b para binario |
| Cero de relleno | 0 | Rellenar con ceros en lugar de espacios |
| Ancho | entero | Ancho mínimo del campo |
| Agrupación | , o _ | Separador de miles |
| Precisión | .n | Posiciones decimales (floats) o máximo de caracteres (strings) |
| Tipo | d f e g x o b % | Entero, float, científico, general, hex, octal, binario, porcentaje |
Alineación y Ancho
text = "hello"
print(f"{text:<10}|") # left-aligned in 10-char field
# hello |
print(f"{text:>10}|") # right-aligned
# hello|
print(f"{text:^10}|") # centered
# hello |
print(f"{text:*^10}|") # centered, filled with *
# **hello***|Los mismos especificadores de alineación funcionan con str.format(). Aquí hay un ejemplo que combina alineación y precisión:
Formateo de Números
x = 123.456789
print(f"{x:.2f}") # two decimal places
# 123.46
print(f"{x:,.2f}") # thousands separator, two decimal places
# 123.46
print(f"{x:+.2f}") # explicit plus sign for positive numbers
# +123.46
print(f"{x:10.2f}") # right-aligned in a 10-char field
# 123.46
print(f"{x:<10.2f}|") # left-aligned
# 123.46 |
print(f"{x:010.2f}") # zero-padded to 10 characters
# 0000123.46Números Grandes y Porcentajes
population = 8_100_000_000
print(f"{population:,}") # comma separator
# 8,100,000,000
print(f"{population:_}") # underscore separator (Python 3.6+)
# 8_100_000_000
ratio = 0.8567
print(f"{ratio:.1%}") # percentage, one decimal place
# 85.7%Bases de Enteros
n = 255
print(f"{n:d}") # decimal (default)
# 255
print(f"{n:x}") # lowercase hexadecimal
# ff
print(f"{n:X}") # uppercase hexadecimal
# FF
print(f"{n:#x}") # hex with 0x prefix
# 0xff
print(f"{n:o}") # octal
# 377
print(f"{n:b}") # binary
# 11111111
print(f"{n:#b}") # binary with 0b prefix
# 0b11111111También puedes usar los mismos especificadores con str.format():
Notación Científica
avogadro = 6.02214076e23
print(f"{avogadro:.3e}") # scientific notation, 3 decimal places
# 6.022e+23
print(f"{avogadro:.3E}") # uppercase E
# 6.022E+23
print(f"{avogadro:.3g}") # general: compact form, removes trailing zeros
# 6.02e+23Formateo de Strings con format() y f-Strings
Los tres enfoques producen la misma salida para una sustitución simple:
Los especificadores específicos de string te permiten controlar el truncamiento y el padding:
s = "Python"
print(f"{s:.3}") # truncate to 3 characters
# Pyt
print(f"{s:10}") # pad to width 10 (left-aligned by default for strings)
# Python
print(f"{s:>10}") # right-aligned
# Python
print(f"{s:*^12}") # centered, filled with *
# ***Python***Formateo de Fechas y Horas
Usa los códigos de formato strftime dentro de las llaves al formatear objetos datetime con f-strings o str.format():
import datetime
date = datetime.datetime(2024, 3, 15, 10, 30, 0)
# Default string representation
print(f"Default: {date}")
# Default: 2024-03-15 10:30:00
# strftime codes inside the format spec
print(f"Formatted: {date:%B %d, %Y}")
# Formatted: March 15, 2024
print(f"Time only: {date:%H:%M:%S}")
# Time only: 10:30:00
print(f"ISO-style: {date:%Y-%m-%d}")
# ISO-style: 2024-03-15La misma sintaxis funciona con str.format():
import datetime
date = datetime.datetime(2024, 3, 15, 10, 30, 0)
print("The date is {:%B %d, %Y}".format(date))
# The date is March 15, 2024Para formateo avanzado de fechas, consulta el capítulo Python Modify Strings que cubre técnicas de manipulación de string.
Técnicas Avanzadas
Expresiones Anidadas en f-Strings
Las f-strings te permiten calcular el especificador de formato de forma dinámica:
width = 10
precision = 3
value = 3.14159
print(f"{value:{width}.{precision}f}")
# output: 3.142 (right-aligned in a 10-char field, 3 decimal places)Especificador de Formato con format() y Variables
La misma técnica funciona con str.format() usando {} anidados:
width = 8
print("{:{width}}".format("left", width=width))
# left Formateo Condicional en f-Strings
Dado que las f-strings evalúan cualquier expresión, puedes usar expresiones condicionales en línea:
score = 73
label = f"{'pass' if score >= 60 else 'fail'}"
print(f"Score {score}: {label}")
# Score 73: passDepuración con = (Python 3.8+)
Agrega = dentro de una f-string para imprimir tanto la expresión como su valor — muy útil para depuración:
x = 42
y = x * 2
print(f"{x=}, {y=}")
# x=42, y=84Errores Comunes
1. Escapado de llaves. Para incluir un { o } literal en cualquier string formateada, duplícalo:
print(f"Use {{curly braces}} in f-strings")
# Use {curly braces} in f-strings2. Comillas dentro de f-strings. En Python 3.11 y anteriores, la expresión dentro de {} no puede usar el mismo tipo de comilla que la f-string exterior:
names = ["Alice", "Bob"]
# Wrong in Python <= 3.11:
# print(f"First: {names[0].upper()}") -- this is fine
# print(f"{'Alice'.upper()}") -- single quotes inside double-quoted f-string is fine
# But nesting the same quotes fails:
# print(f"{names["Alice"]}") -- SyntaxError in <= 3.11
# Safe approach for <= 3.11:
key = "Alice"
print(f"{key.upper()}")
# ALICE3. La trampa de la tupla con %. Al usar el formateo % con un solo valor que es en sí mismo una tupla, envuélvelo:
coords = (10, 20)
# This raises TypeError because % sees a 2-element tuple:
# print("Position: %s" % coords)
# Fix: wrap in a 1-element tuple
print("Position: %s" % (coords,))
# Position: (10, 20)4. str.format() y seguridad. Nunca pases entrada de usuario no confiable como string de formato a str.format() — una plantilla maliciosa puede acceder a atributos de objetos y filtrar datos. Las f-strings siempre son string codificadas en el código fuente, por lo que no son vulnerables a esto.
Comparación Práctica
Aquí está la misma salida producida por los tres métodos en paralelo:
item = "widget"
qty = 42
unit_price = 4.5
# % operator
print("%-12s %4d $%7.2f" % (item, qty, unit_price))
# str.format()
print("{:<12} {:>4} ${:>7.2f}".format(item, qty, unit_price))
# f-string
print(f"{item:<12} {qty:>4} ${unit_price:>7.2f}")
# All print:
# widget 42 $ 4.50Resumen
- Usa f-strings para código Python 3.6+ nuevo: son las más legibles y rápidas.
- Usa
str.format()cuando necesites una string de plantilla reutilizable o debas soportar Python 2.6+. - Usa
%solo en código heredado o cuando trabajes con el módulologging(que difiere el formateo hasta que la entrada de log se emite realmente). - El mini-lenguaje de especificación de formato (
width,precision,align,fill,type) se aplica de la misma manera tanto astr.format()como a las f-strings.
Capítulos relacionados:
- Python f-Strings — guía detallada sobre expresiones f-string y características de Python 3.12
- Python Strings — conceptos básicos de string, indexación y segmentación
- Modify Strings — métodos integrados de string
- Escape Characters — caracteres especiales en strings