Python & AI Tutorials Logo
Programación Python

6. Manejo práctico de cadenas

En el Capítulo 5 aprendiste los fundamentos de trabajar con cadenas: crearlas, acceder a caracteres mediante indexación y slicing, y usar métodos básicos de cadena. Ahora construiremos sobre esa base para explorar operaciones de cadena más sofisticadas que usarás constantemente en programas reales de Python.

Este capítulo se centra en técnicas prácticas de manipulación de cadenas que resuelven problemas cotidianos de programación: separar texto y volver a unirlo, crear salidas formateadas que se vean profesionales. Estas habilidades son esenciales tanto si estás procesando entrada de usuario, generando reportes, leyendo archivos de datos o creando cualquier programa que trabaje con texto.

6.1) Separar y unir cadenas

Una de las tareas más comunes en el procesamiento de texto es dividir una cadena en partes más pequeñas o combinar varias partes en una sola cadena. Python proporciona métodos potentes para ambas operaciones.

6.1.1) Separar cadenas con split()

El método split() divide una cadena en una lista (list) de cadenas más pequeñas basándose en un separador (también llamado delimitador). Esto es increíblemente útil para procesar texto estructurado como datos CSV, entrada de usuario con múltiples valores o oraciones en palabras.

Separación básica por espacio en blanco:

Cuando llamas a split() sin argumentos, divide por cualquier espacio en blanco (espacios, tabulaciones, saltos de línea) y elimina automáticamente las cadenas vacías del resultado:

python
# split_basic.py
sentence = "Python is a powerful programming language"
words = sentence.split()
print(words)  # Output: ['Python', 'is', 'a', 'powerful', 'programming', 'language']
print(len(words))  # Output: 6

Observa cómo split() maneja inteligentemente varios espacios:

python
# split_whitespace.py
messy_text = "Python    is     awesome"
words = messy_text.split()
print(words)  # Output: ['Python', 'is', 'awesome']

Aunque hay múltiples espacios entre las palabras, split() trata cualquier cantidad de espacio en blanco como un único separador y produce una lista limpia.

Separar usando un separador específico:

Puedes especificar exactamente sobre qué carácter o cadena dividir pasándolo como argumento:

python
# split_separator.py
csv_data = "apple,banana,cherry,date"
fruits = csv_data.split(',')
print(fruits)  # Output: ['apple', 'banana', 'cherry', 'date']
 
date_string = "2024-03-15"
parts = date_string.split('-')
print(parts)  # Output: ['2024', '03', '15']
year = parts[0]
month = parts[1]
day = parts[2]
print(f"Year: {year}, Month: {month}, Day: {day}")  # Output: Year: 2024, Month: 03, Day: 15

Diferencia importante: Cuando especificas un separador, split() lo trata literalmente y creará cadenas vacías si el separador aparece de forma consecutiva:

python
# split_empty_strings.py
data = "apple,,cherry"
result = data.split(',')
print(result)  # Output: ['apple', '', 'cherry']
print(len(result))  # Output: 3

La cadena vacía '' en el medio representa la “nada” entre las dos comas consecutivas. Este comportamiento es diferente de dividir por espacio en blanco sin argumentos.

Limitando el número de divisiones:

Puedes controlar cuántas divisiones ocurren pasando un segundo argumento (maxsplit):

python
# split_maxsplit.py
text = "one:two:three:four:five"
parts = text.split(':', 2)  # Divide solo en los primeros 2 dos puntos
print(parts)  # Output: ['one', 'two', 'three:four:five']

Esto crea como máximo 3 partes (maxsplit + 1) porque deja de dividir después del número de divisiones especificado. El resto de la cadena permanece intacto.

Ejemplo práctico: Procesar entrada de usuario

python
# process_input.py
user_input = input("Enter your full name: ")
# User enters: "Alice Marie Johnson"
 
name_parts = user_input.split()
if len(name_parts) >= 2:
    first_name = name_parts[0]
    last_name = name_parts[-1]  # Último elemento
    print(f"First name: {first_name}")  # Output: First name: Alice
    print(f"Last name: {last_name}")    # Output: Last name: Johnson
else:
    print("Please enter at least a first and last name")

6.1.2) Unir cadenas con join()

El método join() es lo opuesto de split(): combina una lista (list) (o cualquier iterable) de cadenas en una sola cadena, con un separador entre cada elemento. La sintaxis puede parecer invertida al principio: la cadena separadora llama al método y la lista se pasa como argumento.

Unión básica:

python
# join_basic.py
words = ['Python', 'is', 'awesome']
sentence = ' '.join(words)
print(sentence)  # Output: Python is awesome
 
csv_line = ','.join(['apple', 'banana', 'cherry'])
print(csv_line)  # Output: apple,banana,cherry

La cadena que llama a join() (como ' ' o ',') se convierte en el separador entre elementos.

Por qué la sintaxis es separator.join(list):

Esta sintaxis tiene sentido si lo piensas desde la perspectiva del separador: “Quiero unir estos elementos, insertándome entre cada par.” También permite encadenar de forma elegante y hace que el separador sea muy visible en tu código.

Unir con diferentes separadores:

python
# join_separators.py
items = ['eggs', 'milk', 'bread', 'butter']
 
# Separado por comas
print(', '.join(items))  # Output: eggs, milk, bread, butter
 
# Separado por saltos de línea (cada elemento en su propia línea)
print('\n'.join(items))
# Output:
# eggs
# milk
# bread
# butter
 
# Separado por guiones
print('-'.join(items))  # Output: eggs-milk-bread-butter
 
# Sin separador (concatenación)
print(''.join(items))  # Output: eggsmilkbreadbutter

Importante: join() solo funciona con cadenas:

Todos los elementos del iterable deben ser cadenas. Si intentas unir números u otros tipos, obtendrás un error:

python
# join_error.py
numbers = [1, 2, 3, 4]
# result = ','.join(numbers)  # This would cause: TypeError: sequence item 0: expected str instance, int found

Para unir elementos que no son cadenas, conviértelos primero a cadenas. Aprenderemos una forma más elegante de hacer esto en el Capítulo 34, pero por ahora, puedes convertir cada elemento manualmente:

python
# join_numbers.py
numbers = [1, 2, 3, 4]
# Convierte cada número a cadena manualmente
string_numbers = [str(numbers[0]), str(numbers[1]), str(numbers[2]), str(numbers[3])]
result = ','.join(string_numbers)
print(result)  # Output: 1,2,3,4

Ejemplo práctico: Construir rutas de archivos

python
# build_path.py
path_parts = ['home', 'user', 'documents', 'report.txt']
# En sistemas tipo Unix (Linux, macOS)
unix_path = '/'.join(path_parts)
print(unix_path)  # Output: home/user/documents/report.txt
 
# En Windows
windows_path = '\\'.join(path_parts)
print(windows_path)  # Output: home\user\documents\report.txt

Nota: En el Capítulo 26 aprenderemos sobre el módulo os.path, que proporciona un mejor manejo de rutas multiplataforma, pero esto demuestra el concepto de unir.

6.1.3) Combinar split() y join() para procesamiento de texto

Estos dos métodos funcionan muy bien juntos para transformar texto. Al combinarlos, puedes limpiar entrada desordenada, convertir entre formatos o extraer y reorganizar datos:

python
# transform_text.py
# Reemplaza múltiples espacios por espacios simples
messy = "Python    is     really    cool"
clean = ' '.join(messy.split())
print(clean)  # Output: Python is really cool
 
# Convierte datos separados por comas a separados por espacios
csv_data = "apple,banana,cherry"
space_separated = ' '.join(csv_data.split(','))
print(space_separated)  # Output: apple banana cherry
 
# Elimina todos los espacios
text_with_spaces = "H e l l o"
no_spaces = ''.join(text_with_spaces.split())
print(no_spaces)  # Output: Hello

6.1.4) Otros métodos de separación

Python proporciona métodos adicionales de separación para casos de uso específicos:

rsplit() - Divide desde la derecha:

python
# rsplit_example.py
path = "folder/subfolder/file.txt"
 
# split normal con maxsplit
parts = path.split('/', 1)
print(parts)  # Output: ['folder', 'subfolder/file.txt']
 
# rsplit divide desde la derecha
parts = path.rsplit('/', 1)
print(parts)  # Output: ['folder/subfolder', 'file.txt']

Esto es útil cuando quieres separar la última parte de una cadena de todo lo que viene antes.

splitlines() - Divide en saltos de línea:

python
# splitlines_example.py
multiline = "Line 1\nLine 2\nLine 3"
lines = multiline.splitlines()
print(lines)  # Output: ['Line 1', 'Line 2', 'Line 3']
 
# Funciona con diferentes estilos de fin de línea
mixed_lines = "Line 1\nLine 2\r\nLine 3\rLine 4"
all_lines = mixed_lines.splitlines()
print(all_lines)  # Output: ['Line 1', 'Line 2', 'Line 3', 'Line 4']

El método splitlines() reconoce todas las convenciones estándar de salto de línea (\n, \r\n, \r) y divide en consecuencia, lo que lo hace más robusto que split('\n') para procesar texto de diferentes fuentes.

6.2) Formatear cadenas con f-Strings

Crear salida formateada es una de las tareas más comunes en programación. Necesitas combinar texto con valores de variables, alinear columnas, formatear números y crear salidas legibles para usuarios. Las f-strings (literal de cadena formateada, formatted string literals) de Python proporcionan la forma más moderna, legible y potente de hacer esto.

6.2.1) Sintaxis básica de f-Strings

Una f-string es un literal de cadena prefijado con f o F que puede contener expresiones dentro de llaves {}. Python evalúa estas expresiones y convierte sus resultados a cadenas:

python
# fstring_basic.py
name = "Alice"
age = 30
greeting = f"Hello, {name}! You are {age} years old."
print(greeting)  # Output: Hello, Alice! You are 30 years old.

Las expresiones dentro de {} pueden ser cualquier expresión válida de Python:

python
# fstring_expressions.py
x = 10
y = 20
result = f"The sum of {x} and {y} is {x + y}"
print(result)  # Output: The sum of 10 and 20 is 30
 
price = 19.99
quantity = 3
total = f"Total cost: ${price * quantity}"
print(total)  # Output: Total cost: $59.97

6.2.2) Por qué las f-Strings son mejores que los enfoques antiguos

Antes de las f-strings (introducidas en Python 3.6), los programadores usaban concatenación de cadenas o el método format(). Comparemos:

Concatenación de cadenas (la forma antigua y propensa a errores):

python
# concatenation_example.py
name = "Bob"
age = 25
# Requiere convertir números a cadenas y muchos operadores +
message = "Hello, " + name + "! You are " + str(age) + " years old."
print(message)  # Output: Hello, Bob! You are 25 years old.

Este enfoque es verboso, propenso a errores (olvidar str() causa errores) y difícil de leer con muchas variables.

f-Strings (la forma moderna y limpia):

python
# fstring_clean.py
name = "Bob"
age = 25
message = f"Hello, {name}! You are {age} years old."
print(message)  # Output: Hello, Bob! You are 25 years old.

Las f-strings convierten automáticamente los valores a cadenas, son más legibles y en realidad son más rápidas que otros enfoques.

6.2.3) Expresiones y llamadas a métodos en f-Strings

Puedes incluir expresiones complejas, llamadas a métodos e incluso llamadas a funciones dentro de f-strings:

python
# fstring_methods.py
name = "alice"
print(f"Capitalized: {name.capitalize()}")  # Output: Capitalized: Alice
print(f"Uppercase: {name.upper()}")  # Output: Uppercase: ALICE
print(f"Length: {len(name)}")  # Output: Length: 5
 
# Aritmética y comparaciones
x = 10
print(f"Is {x} even? {x % 2 == 0}")  # Output: Is 10 even? True
 
# Indexación y slicing
text = "Python"
print(f"First letter: {text[0]}")  # Output: First letter: P
print(f"First three: {text[:3]}")  # Output: First three: Pyt

6.2.4) Formatear números en f-Strings

Las f-strings admiten especificadores de formato que controlan cómo se muestran los valores. La sintaxis es {expression:format_spec}:

Controlar decimales para flotantes:

python
# fstring_decimals.py
pi = 3.14159265359
 
print(f"Default: {pi}")  # Output: Default: 3.14159265359
print(f"2 decimals: {pi:.2f}")  # Output: 2 decimals: 3.14
print(f"4 decimals: {pi:.4f}")  # Output: 4 decimals: 3.1416
print(f"No decimals: {pi:.0f}")  # Output: No decimals: 3

El especificador de formato .2f significa “formatea como flotante con 2 decimales”. La f significa “notación de punto fijo” (fixed-point notation).

Formatear con separadores de miles:

python
# fstring_thousands.py
large_number = 1234567890
 
print(f"No separator: {large_number}")  # Output: No separator: 1234567890
print(f"With commas: {large_number:,}")  # Output: With commas: 1,234,567,890
print(f"With underscores: {large_number:_}")  # Output: With underscores: 1_234_567_890
 
# Combinado con decimales
price = 1234567.89
print(f"Price: ${price:,.2f}")  # Output: Price: $1,234,567.89

Formateo de porcentajes:

python
# fstring_percentage.py
ratio = 0.847
print(f"Ratio: {ratio}")  # Output: Ratio: 0.847
print(f"Percentage: {ratio:.1%}")  # Output: Percentage: 84.7%
print(f"Percentage: {ratio:.2%}")  # Output: Percentage: 84.70%

El especificador de formato % multiplica por 100 y añade el signo de porcentaje.

6.2.5) Ejemplos prácticos con f-Strings

Crear reportes formateados:

python
# report_example.py
product = "Laptop"
price = 899.99
quantity = 5
tax_rate = 0.08
 
subtotal = price * quantity
tax = subtotal * tax_rate
total = subtotal + tax
 
print(f"Product: {product}")  # Output: Product: Laptop
print(f"Price: ${price:.2f}")  # Output: Price: $899.99
print(f"Quantity: {quantity}")  # Output: Quantity: 5
print(f"Subtotal: ${subtotal:.2f}")  # Output: Subtotal: $4499.95
print(f"Tax (8%): ${tax:.2f}")  # Output: Tax (8%): $360.00
print(f"Total: ${total:.2f}")  # Output: Total: $4859.95

Crear mensajes amigables para el usuario:

python
# user_messages.py
username = "Alice"
login_count = 42
last_login = "2024-03-15"
 
welcome = f"Welcome back, {username}!"
stats = f"You've logged in {login_count} times. Last login: {last_login}"
 
print(welcome)  # Output: Welcome back, Alice!
print(stats)  # Output: You've logged in 42 times. Last login: 2024-03-15

6.2.6) Depuración (debugging) con f-Strings

Python 3.8 introdujo el especificador = para depuración, que muestra tanto la expresión como su valor:

python
# fstring_debug.py
x = 10
y = 20
z = x + y
 
print(f"{x=}")  # Output: x=10
print(f"{y=}")  # Output: y=20
print(f"{z=}")  # Output: z=30
print(f"{x + y=}")  # Output: x + y=30

Esto es increíblemente útil para comprobar rápidamente valores de variables durante el desarrollo sin escribir el nombre de la variable dos veces.

6.2.7) Escapar llaves en f-Strings

Si necesitas llaves literales en una f-string, duplica las llaves:

python
# fstring_escape.py
value = 42
# Llaves simples son marcadores de expresión
print(f"Value: {value}")  # Output: Value: 42
 
# Llaves dobles producen llaves literales
print(f"Use {{value}} as a placeholder")  # Output: Use {value} as a placeholder
print(f"The value is {value}, shown as {{value}}")  # Output: The value is 42, shown as {value}

6.3) Formateo con format() y especificadores de formato

Aunque las f-strings son el enfoque moderno preferido, el método format() sigue siendo muy usado y ofrece algunas capacidades que es útil entender. También es la base sobre la que se construyen las f-strings, por lo que entender format() te ayuda a entender mejor las f-strings.

6.3.1) Sintaxis básica de format()

El método format() usa llaves {} como marcadores de posición en una cadena, y los valores que se insertan se pasan como argumentos:

python
# format_basic.py
template = "Hello, {}! You are {} years old."
message = template.format("Alice", 30)
print(message)  # Output: Hello, Alice! You are 30 years old.
 
# Usos múltiples de format()
greeting = "Hello, {}!".format("Bob")
print(greeting)  # Output: Hello, Bob!

6.3.2) Argumentos posicionales y con nombre (keyword)

Puedes controlar qué argumento va en cada lugar usando números de posición o nombres:

Argumentos posicionales:

python
# format_positional.py
# Orden predeterminado (0, 1, 2, ...)
template = "{} + {} = {}"
result = template.format(5, 3, 8)
print(result)  # Output: 5 + 3 = 8
 
# Posiciones explícitas
template = "{0} + {1} = {2}"
result = template.format(5, 3, 8)
print(result)  # Output: 5 + 3 = 8
 
# Reordenar y reutilizar
template = "{2} = {0} + {1}"
result = template.format(5, 3, 8)
print(result)  # Output: 8 = 5 + 3
 
# Reutilizar el mismo valor
template = "{0} times {0} equals {1}"
result = template.format(7, 49)
print(result)  # Output: 7 times 7 equals 49

Argumentos con nombre (keyword arguments):

python
# format_keyword.py
template = "Hello, {name}! You are {age} years old."
message = template.format(name="Alice", age=30)
print(message)  # Output: Hello, Alice! You are 30 years old.
 
# Se puede mezclar con posicionales (los posicionales deben ir primero)
template = "{0}, your score is {score} out of {1}"
result = template.format("Alice", 100, score=95)
print(result)  # Output: Alice, your score is 95 out of 100

6.3.3) Especificadores de formato con format()

Los especificadores de formato funcionan igual en format() que en las f-strings, usando el separador ::

python
# format_specifiers.py
pi = 3.14159265359
 
print("{:.2f}".format(pi))  # Output: 3.14
print("{:.4f}".format(pi))  # Output: 3.1416
 
# Con nombres
print("{value:.2f}".format(value=pi))  # Output: 3.14
 
# Valores múltiples con diferentes formatos
template = "{name}'s score is {score:.1f}%"
result = template.format(name="Bob", score=87.654)
print(result)  # Output: Bob's score is 87.7%

6.3.4) Cuándo usar format() en lugar de f-Strings

Las f-strings se prefieren generalmente, pero format() es útil en situaciones específicas:

1. Cadenas plantilla (template strings) definidas por separado de los datos:

python
# format_templates.py
# Plantilla definida una vez, usada múltiples veces con diferentes datos
email_template = "Dear {name},\n\nYour order #{order_id} has shipped.\n\nThank you!"
 
# Usar la plantilla con diferentes clientes
message1 = email_template.format(name="Alice", order_id=12345)
message2 = email_template.format(name="Bob", order_id=12346)
 
print(message1)
# Output:
# Dear Alice,
#
# Your order #12345 has shipped.
#
# Thank you!
 
print(message2)
# Output:
# Dear Bob,
#
# Your order #12346 has shipped.
#
# Thank you!

2. Cuando la plantilla proviene de fuentes externas:

python
# format_external.py
# La plantilla podría venir de un archivo de configuración o una base de datos
# (Aprenderemos a leer archivos en el Capítulo 24)
user_template = input("Enter message template: ")
# User enters: "Hello, {name}! Welcome to {place}."
 
message = user_template.format(name="Charlie", place="Python")
print(message)  # Output: Hello, Charlie! Welcome to Python.

Con f-strings, la plantilla debe estar en tu código porque las expresiones se evalúan inmediatamente. Con format(), la plantilla puede ser una cadena normal que venga de cualquier sitio.

6.3.5) Acceder a atributos de objetos y claves de diccionarios

El método format() puede acceder directamente a atributos y claves de diccionarios:

python
# format_access.py
# Acceso a diccionario
person = {"name": "Alice", "age": 30, "city": "Boston"}
message = "Name: {0[name]}, Age: {0[age]}, City: {0[city]}".format(person)
print(message)  # Output: Name: Alice, Age: 30, City: Boston
 
# Con argumento keyword
message = "{p[name]} is {p[age]} years old".format(p=person)
print(message)  # Output: Alice is 30 years old

Nota: Aprenderemos sobre atributos de objetos en el Capítulo 30, pero esto demuestra que format() puede acceder a estructuras de datos anidadas.

6.4) Alinear y redondear números en salida formateada

Una salida con aspecto profesional a menudo requiere un alineado cuidadoso y un buen formateo de números. Tanto las f-strings como format() proporcionan herramientas potentes para crear tablas, reportes y pantallas bien formateados.

6.4.1) Alineación de texto

Puedes controlar el ancho y la alineación de los valores usando especificadores de formato:

python
# alignment_basic.py
# Sintaxis: {value:width}
# El valor predeterminado es alineado a la izquierda para cadenas, a la derecha para números
 
name = "Alice"
print(f"|{name}|")      # Output: |Alice|
print(f"|{name:10}|")   # Output: |Alice     |  (alineado a la izquierda, ancho 10)
print(f"|{name:>10}|")  # Output: |     Alice|  (alineado a la derecha)
print(f"|{name:^10}|")  # Output: |  Alice   |  (centrado)

Los especificadores de alineación son:

  • < : Alinear a la izquierda (predeterminado para cadenas)
  • > : Alinear a la derecha (predeterminado para números)
  • ^ : Centrar

Alineación con números:

python
# alignment_numbers.py
value = 42
print(f"|{value}|")      # Output: |42|
print(f"|{value:5}|")    # Output: |   42|  (alineado a la derecha por defecto)
print(f"|{value:<5}|")   # Output: |42   |  (alineado a la izquierda)
print(f"|{value:^5}|")   # Output: | 42  |  (centrado)

6.4.2) Caracteres de relleno personalizados

Puedes especificar un carácter para rellenar el espacio vacío:

python
# alignment_fill.py
name = "Bob"
print(f"|{name:*<10}|")  # Output: |Bob*******|
print(f"|{name:*>10}|")  # Output: |*******Bob|
print(f"|{name:*^10}|")  # Output: |***Bob****|
 
# Útil para crear separadores visuales
print(f"{name:=^20}")    # Output: ========Bob=========

La sintaxis es {value:fill_char align width}.

6.4.3) Combinar alineación con formateo de números

Puedes combinar ancho, alineación y formateo de números:

python
# alignment_combined.py
price = 19.99
quantity = 5
total = price * quantity
 
# Alinear a la derecha con ancho 10, 2 decimales
print(f"Price:    ${price:>10.2f}")     # Output: Price:    $     19.99
print(f"Quantity: {quantity:>10}")      # Output: Quantity:          5
print(f"Total:    ${total:>10.2f}")     # Output: Total:    $     99.95
 
# Con carácter de relleno para efecto visual
print(f"Total:    ${total:>10.2f}".replace(' ', '.'))  # Output: Total:....$.....99.95

En este capítulo has aprendido técnicas esenciales de manipulación de cadenas que usarás en prácticamente todos los programas de Python: separar y unir cadenas para procesamiento de texto, crear salida formateada con f-strings y especificadores de formato, alinear y formatear números para presentaciones profesionales.

Estas habilidades forman la base para trabajar con datos de texto en Python. Ahora puedes procesar entrada de usuario, crear reportes formateados, manejar datos desde archivos (que cubriremos en el Capítulo 24). A medida que sigas aprendiendo Python, usarás constantemente estas técnicas de manejo de cadenas, así que prácticalas hasta que se vuelvan algo natural para ti.

© 2025. Primesoft Co., Ltd.
support@primesoft.ai