AulaML Python · C++
Python principiante · 42 min · Estructuras de datos

Strings, índices y slicing

Cómo leer, cortar y transformar texto sin mutarlo ni perder caracteres por el camino

Un string es una secuencia inmutable de caracteres. Aprenderás a acceder a sus posiciones, cortarlo con start, stop y step, transformarlo con métodos y unir o separar texto para procesar mensajes, correos y datos reales.

Lección 1 de 4 del módulo
Al terminar esta lección podrás
  • Explicar por qué un string es inmutable y qué consecuencias tiene
  • Acceder a caracteres con índices positivos y negativos sin salirte del rango
  • Escribir slices con inicio, fin y salto, incluido el recorrido inverso
  • Usar los métodos más habituales y distinguir cuáles devuelven una cadena nueva
  • Construir mensajes con f-strings y procesar texto con split y join

Antes necesitas: Variables y tipos de datos · Bucles: while, for y control de iteraciones

En esta lección
  1. ¿Qué es un string?
  2. ¿Para qué sirve?
  3. ¿Cómo funciona por dentro?
  4. Sintaxis: comillas, escapes y f-strings
  5. Ejemplo básico: leer posiciones
  6. Ejemplo intermedio: normalizar un correo
  7. Caso práctico: interpretar un mensaje de chat
  8. Visualización: índices, slicing y recorrido
  9. Errores comunes
  10. Buenas prácticas
  11. Ejercicios
  12. Soluciones explicadas
  13. Resumen
  14. Evaluación

Hasta ahora has guardado números y textos en variables, pero apenas los has manipulado. La mayor parte de lo que un programa recibe del exterior llega como texto: un mensaje de chat, una línea de CSV, el nombre de un archivo. Si no sabes cortarlo y limpiarlo, no puedes convertirlo en datos útiles.

En esta lección vas a aprender a ver un string como lo que realmente es: una secuencia ordenada de caracteres con posiciones numeradas. Esa idea, que parece simple, es la que explica los índices, el slicing, los métodos y hasta los errores que verás cuando algo se sale de rango.

¿Qué es un string?

Un string o cadena de texto es una secuencia ordenada e inmutable de caracteres. Se representa con el tipo str y se escribe entre comillas simples o dobles: "hola" y 'hola' son el mismo valor. Imagina un collar de cuentas: cada cuenta es un carácter y puedes señalar la tercera sin desmontarlo.

Inmutable significa que el contenido de una cadena no cambia nunca. Si escribes saludo[0] = "H", Python lanza un TypeError: esa posición no se puede reasignar. Lo que sí puedes hacer es crear otra cadena y apuntar la variable hacia ella. Distinguir entre cambiar la variable y mutar el objeto será clave con las listas.

¿Para qué sirve?

Cualquier tarea que implique leer, validar o presentar información escrita termina usando strings. Estos son casos que aparecerán una y otra vez en el curso y en el trabajo real:

  • Procesar mensajes: separar el comando de sus argumentos en un bot de chat y normalizar mayúsculas.
  • Leer datos tabulares: cada línea de un CSV es un string que hay que dividir por comas y convertir al tipo adecuado.
  • Limpiar entradas: correos con mayúsculas mezcladas o nombres con espacios al inicio.
  • Preparar texto para NLP: pasar a minúsculas, quitar puntuación y separar en palabras antes de contar frecuencias.
  • Generar informes y rutas: componer mensajes con f-strings o nombres como resultados_2026.csv.

¿Cómo funciona por dentro?

CPython almacena el texto como una secuencia contigua de puntos de código Unicode. Gracias a esa contigüidad, acceder a una posición concreta mediante s[i] es una operación de coste constante: el intérprete calcula dónde empieza la cadena y salta directamente a la posición pedida. No tiene que recorrer los caracteres anteriores.

Cada carácter ocupa una posición, no un byte. len("café") devuelve 4, aunque la é ocupe dos bytes en UTF-8, y un emoji habitual cuenta como un carácter. Para tamaños en bytes usarás s.encode("utf-8"), algo que aparecerá al leer archivos. Por ahora quédate con que Python indexa caracteres.

Un slice no es una vista: construye una cadena nueva con los caracteres seleccionados, así que cuesta tiempo proporcional a lo que copias. Concatenar con + dentro de un bucle es aún más caro, porque en cada vuelta se copia todo lo anterior y el coste crece de forma cuadrática.

OperaciónEjemploCosteQué ocurre
Índices[3]O(1)Devuelve el carácter de esa posición
Slices[2:7]O(k)Copia los k caracteres seleccionados
Longitudlen(s)O(1)La longitud se guarda con el objeto
Búsquedas.find("x")O(n)Recorre hasta encontrar o llegar al final
Concatenar en bucles += trozoO(n²)Crea y copia una cadena nueva cada vez

Sintaxis: comillas, escapes y f-strings

Elige comillas simples o dobles según el contenido: si el texto lleva apóstrofes, usa dobles. Las comillas triples permiten varias líneas sin \n. La barra invertida introduce caracteres especiales, y una r crea una cadena raw, donde no se interpretan.

PYTHON Formas de escribir un string
# Comillas simples y dobles son equivalentes
saludo = 'Hola'
otro = "Hola"

# Escapes: salto de línea, tabulador y comilla
mensaje = "Primera línea\nSegunda línea"
con_comilla = 'Dijo: "hola"'

# Varias líneas con comillas triples
poema = """Rima LIII
Volverán las oscuras golondrinas"""

# Cadena raw: la barra es literal
ruta = r"C:\datos\nuevo.csv"

# f-string: inserta expresiones dentro de llaves
precio = 120
print(f"Total con IGV: {precio * 1.18:.2f}")
  • \n salta de línea, \t inserta un tabulador y \\ escribe una barra invertida.
  • Las comillas triples """...""" conservan los saltos de línea que escribas dentro.
  • Una f delante de las comillas activa la interpolación: f"Hola, {nombre}".
  • Dentro de las llaves de una f-string cabe cualquier expresión, no solo un nombre de variable.
  • Para escribir una llave literal en una f-string, duplícala: f"{{esto no se evalúa}}".

Ejemplo básico: leer posiciones

PYTHON presentacion.py
nombre = "Ada"
apellido = "Lovelace"
nombre_completo = nombre + " " + apellido
inicial = nombre_completo[0]
print(nombre_completo)
print(f"Inicial: {inicial} | Longitud: {len(nombre_completo)}")
print(nombre_completo[-1])

Las dos primeras líneas guardan los textos. En la tercera, el operador + une tres cadenas y produce una nueva; el espacio del medio es un string de un solo carácter. En la cuarta, nombre_completo[0] pide la posición cero, que es "A": Python empieza a contar en cero, igual que los índices de un vector.

La quinta línea imprime la cadena. La sexta usa una f-string con inicial y len(nombre_completo); la longitud es 12, porque hay doce caracteres contando el espacio. La última línea usa el índice -1, el último carácter; con [-2] obtendrías "c".

Ejemplo intermedio: normalizar un correo

Las entradas reales casi nunca llegan limpias. Supón que un formulario entrega " Ada.Lovelace@Example.COM ". Conviene quitar los espacios de los extremos, pasar a minúsculas y separar la parte local del dominio. Observa cómo se encadenan los métodos:

PYTHON correo.py
entrada = "  Ada.Lovelace@Example.COM "
correo = entrada.strip().lower()
usuario, dominio = correo.split("@")

print(correo)
print(usuario.replace(".", "_"))
print(dominio.endswith(".com"))

strip() elimina espacios y saltos de línea de ambos extremos, pero no los del interior. lower() pasa a minúsculas. Como cada método devuelve una cadena, se encadenan de izquierda a derecha: primero limpiar, luego normalizar. El resultado es "ada.lovelace@example.com".

split("@") corta la cadena por el arroba y devuelve una lista de dos elementos. La asignación usuario, dominio = ... desempaqueta esa lista: exige exactamente dos valores y falla si hay más o menos, lo que aquí funciona como validación implícita. Después, replace(".", "_") sustituye todos los puntos del usuario, y endswith(".com") comprueba el final del dominio y devuelve un booleano.

Caso práctico: interpretar un mensaje de chat

Un bot recibe mensajes con la forma /clima Lima Este 2: una barra, un comando, una ciudad que puede tener varias palabras y un número de días. El programa debe extraer cada parte. Este es el tipo de análisis que hay que hacer antes de llamar a cualquier API.

PYTHON comando.py
mensaje = "/clima Lima Este 2"
partes = mensaje.strip().split()

comando = partes[0]
if comando.startswith("/"):
    comando = comando[1:]

ciudad = " ".join(partes[1:-1])
dias = int(partes[-1])

print(f"Comando: {comando}")
print(f"Ciudad: {ciudad} | Días: {dias}")

split() sin argumentos trata cualquier bloque de espacios como separador y descarta los vacíos. partes[0] es "/clima"; el slice [1:] elimina la barra y deja "clima". Para la ciudad se usa partes[1:-1], que excluye los extremos, y join las vuelve a unir con espacio para no perder "Lima Este". El último elemento se convierte a entero; con letras, int lanzaría ValueError.

Visualización: índices, slicing y recorrido

Un slice se escribe cadena[inicio:fin:salto]. El inicio es la primera posición que quieres; el fin es exclusivo, es decir, el corte se detiene justo antes de esa posición; y el salto indica cuántas posiciones avanzar. Si omites inicio, empieza en el borde correspondiente; si omites fin, llega hasta el otro borde. Un salto negativo recorre la cadena de derecha a izquierda.

Slicing interactivo ·Recorrido con salto negativo
cadena[6:1:-2]='gec'
01234567
-8-7-6-5-4-3-2-1
← de derecha a izquierda
seleccionados: 3 inicio: 6 fin (exclusivo): 1 Paso de -2

La cadena abcdefgh tiene índices 0 a 7. Con inicio 6 se empieza en 'g'; el salto -2 visita 6, 4 y 2; el fin 1 es exclusivo, así que el recorrido se detiene antes de llegar a la posición 1 y no incluye la 0. Resultado: 'gec'.

Haz clic en un carácter para fijar el inicio; con Shift+clic fijas el fin. Ajusta el salto para ver el recorrido.

Sigue el recorrido: se toma el índice 6 (g), se resta 2 y se toma el 4 (e), se resta 2 y se toma el 2 (c). El siguiente sería 0, pero con salto negativo el recorrido se detiene cuando el índice es menor o igual que el fin; como 0 <= 1, termina y el resultado es "gec". Con fin -1, el 0 entraría y obtendrías "geca".

PYTHON slices.py
s = "abcdefgh"
print(s[2:5])
print(s[:3])
print(s[-2:])
print(s[::-1])
print(s[6:1:-2])

s[2:5] toma las posiciones 2, 3 y 4 y produce "cde". s[:3] equivale a s[0:3] y da "abc". s[-2:] empieza dos posiciones antes del final: "gh". s[::-1] recorre con salto -1 y devuelve "hgfedcba". La última línea confirma "gec".

Ejecución visual ·Qué ocurre al limpiar y unir palabras
1 / 6
1 texto = " Hola, mundo "
2 limpio = texto.strip()
3 inicial = limpio[0]
4 palabras = limpio.split()
5 unido = "-".join(palabras)
6 print(unido.upper())
Se crea texto con dos espacios a cada lado. Los espacios también son caracteres y ocupan posiciones.
Variables
texto = ' Hola, mundo '
Salida
—

Avanza paso a paso: observa la línea resaltada, las variables y la salida.

Errores comunes

Mensaje o comportamientoPor qué ocurreCómo se arregla
IndexError: string index out of rangeLa posición no existeComprueba len(s) o usa un slice
TypeError: 'str' object does not support item assignmentIntentaste modificar una posiciónCrea una cadena nueva con s[:i] + nuevo + s[i+1:]
Un método parece no hacer nadaNo guardaste su valor de retornoAsigna el resultado: s = s.strip()
TypeError: can only concatenate str (not "int") to strSumaste texto y númeroConvierte con str(n) o usa una f-string
El slice devuelve ""Inicio y fin no dejan caracteres entre ellosRevisa el orden: fin debe superar a inicio
Cambiar una letra de un string
Incorrecto
PYTHON TypeError
s = "casa"
s[0] = "C"
print(s)
Correcto
PYTHON Correcto
s = "casa"
s = "C" + s[1:]
print(s)

Los strings son inmutables: no admiten asignación por índice. La alternativa es construir otra cadena combinando la parte anterior, el carácter nuevo y la parte posterior. Para una sola letra, `s.replace("c", "C", 1)` también sirve.

Cuando un slice no selecciona nada devuelve la cadena vacía, sin excepción. Es cómodo para código defensivo, pero puede ocultar un error de lógica: si esperabas "cde" y obtienes "", revisa el orden de los índices.

Buenas prácticas

  • Usa f-strings para construir mensajes: son más legibles y rápidas que concatenar con + y str().
  • Para unir muchos fragmentos, acumula en una lista y aplica "".join(lista) una sola vez.
  • Normaliza al principio: strip() y lower() evitan fallos por un espacio o una mayúscula.
  • Prefiere startswith y endswith a cortar con slices para comprobar un extremo.
  • Los métodos devuelven cadenas nuevas: s.strip() sin asignación no hace nada visible.
  • Usa comillas triples solo para texto multilínea; el resto se lee mejor en una línea.
Texto en Python y en C++
Python
PYTHON texto.py
s = "Hola"
s = s.lower()
parte = s[1:3]
print(f"{parte} {len(s)}")
C++
CPP texto.cpp
#include <cctype>
#include <iostream>
#include <string>

int main() {
    std::string s = "Hola";
    for (char& c : s) c = static_cast<char>(std::tolower(c));
    std::string parte = s.substr(1, 2);
    std::cout << parte << " " << s.size() << std::endl;
    return 0;
}

En Python `lower()` devuelve una cadena nueva; en C++ hay que recorrer y modificar el `std::string`, que sí es mutable. El slice `s[1:3]` equivale a `substr(1, 2)`: en C++ el segundo argumento es la cantidad de caracteres, no el índice final.

Ejercicios

Ejercicio 1

Iniciales y vocales

Pide un nombre completo separado por espacios, por ejemplo "Ada King Lovelace". Muestra sus iniciales unidas por puntos (sin punto final) y cuenta cuántas vocales contiene el nombre, ignorando mayúsculas. Resuélvelo con un bucle sobre la cadena y un contador.
Pista

Convierte a minúsculas antes de contar y comprueba si cada carácter pertenece a la cadena "aeiou" con el operador in.

Completar código Completa el corte
s = "abcdefgh"
print(s[:])   # debe mostrar cdef
print(s[])       # debe mostrar h
print(s[])       # debe mostrar a

El fin del slice es exclusivo: para incluir la f hay que escribir 6. El último índice también se escribe con un número negativo.

Ejercicio 2

Nombre de usuario

A partir de " Ada King Lovelace ", genera un usuario con la forma a.lovelace: la inicial del primer nombre, un punto y el último apellido, todo en minúsculas y sin espacios sobrantes. Muestra también el correo corporativo añadiendo @aula.ml.
Pista

Limpia, pasa a minúsculas y usa split() para obtener las partes. El último apellido está en el índice -1.

Soluciones explicadas

En el primer ejercicio, nombre[0] solo funciona con un nombre. Al dividir en palabras obtienes una estructura iterable y el mismo código sirve para dos o cinco nombres. La parte de las vocales muestra que un string se recorre con for igual que una lista: cada iteración entrega un carácter.

En el segundo, el orden importa: strip() antes de split() evita palabras vacías y lower() garantiza un formato uniforme. No hay ningún bucle explícito porque los métodos recorren por dentro. Esa es la señal de que empiezas a pensar en operaciones sobre secuencias.

Resumen

  • Un string es una secuencia ordenada e inmutable; sus métodos devuelven cadenas nuevas.
  • Los índices empiezan en 0; los negativos cuentan desde el final (-1 es el último).
  • El slice s[a:b:c] incluye a, excluye b y avanza c; con salto negativo va hacia atrás.
  • Un slice fuera de rango no lanza error: se recorta a los límites disponibles.
  • strip, lower, replace, startswith y find resuelven la limpieza habitual.
  • split separa en una lista y join une una lista con el separador que elijas.
  • Las f-strings interpolan expresiones y admiten formato, como :.2f.

Evaluación

Evaluación 1

¿Qué devuelve "Python"[1:4]?

Evaluación 2

Después de s = "hola" y s.upper(), ¿qué contiene s?

Evaluación 3

¿Cuántos elementos produce "a,b,,c".split(",")?

Tus notas

¿Ya lo entendiste?

Márcala como completada para llevar tu progreso y desbloquear el siguiente paso de la ruta.