Trabajar con texto — indexado, slices y f-strings
Sacar trozos de texto, limpiarlo, cambiarlo y construir mensajes legibles con f-strings —más la regla de que el texto no se puede modificar en el sitio—.
¿Cómo quieres aprender?
El problema que vamos a resolver
De un formulario llega un nombre: " Rafi Ahmed ". Espacios de sobra en los dos extremos, y lo que necesitas es solo el nombre de pila, más un mensaje —"Welcome, Rafi!"—.
Ese trabajo —limpiar texto, sacarle trozos y construir algo nuevo a partir de ellos— es una de las tareas más frecuentes de la programación. Nombres de usuario, direcciones de correo, ids, nombres de archivo, direcciones postales, lo que sea que devuelva una API: todo es texto.
Y hoy quedará clara una cosa más, de las que cuestan horas si no la sabes: en Python, el texto no se puede modificar. Escribir name.upper() no pone name en mayúsculas. Por qué no, y qué hacer en su lugar, es la parte más valiosa de este capítulo.
Al terminar este capítulo podrás
- Llegar a cualquier carácter por índice, desde el principio y desde el final
- Sacar un trozo con un slice
- Limpiar y cambiar texto con
strip,upper,lower,replaceysplit - Explicar por qué hay que guardar el resultado de un método
- Construir mensajes legibles con f-strings
Requisitos previos: Aritmética — divisiones, restos y la trampa del decimal.
Comillas — una o dos
Para Python, 'Rafi' y "Rafi" son lo mismo. Las dos existen para que las comillas dentro del texto no den problemas:
print("It's working")
print('She said "yes"')It's working
She said "yes"Tres comillas sostienen texto que ocupa varias líneas:
note = """Dear customer,
Your order is confirmed.
Thank you."""
print(note)Dear customer,
Your order is confirmed.
Thank you.Y \n produce un salto de línea, \t un tabulador:
print("Name:\tRafi\nRole:\tLearner")Name: Rafi
Role: LearnerLongitud e índice
word = "PYTHON"
print(len(word))
print(word[0])
print(word[1])
print(word[-1])
print(word[-2])6
P
Y
N
ODos cosas que dejar claras de una vez:
El conteo empieza en cero. El primer carácter es el índice 0, el segundo el 1. Así que en una palabra de seis caracteres el último índice es 5, no 6. Si pides word[6] recibes un IndexError. Este despiste de "uno de más" es tan común que tiene nombre propio: el error off-by-one.
Los índices negativos cuentan desde atrás. word[-1] es el último carácter, word[-2] el anterior. Es la forma fácil de llegar al final sin conocer la longitud.
Slices — sacar un trozo
word = "PROGRAMMING"
print(word[0:7])
print(word[7:11])
print(word[:7])
print(word[7:])
print(word[-4:])PROGRAM
MING
PROGRAM
MING
MINGword[a:b] significa desde a hasta b, pero sin incluir b. El índice final se deja fuera.
Al principio resulta raro, y a cambio te da algo: word[0:7] y word[7:11] encajan exactamente, sin repetir ni saltarse ningún carácter. Dejar fuera el primer número significa "desde el principio", y dejar fuera el segundo significa "hasta el final".
El texto no se puede modificar
Esta es la regla más importante de este capítulo:
name = "rafi"
name[0] = "R"Traceback (most recent call last):
File "D:\python-lab\lesson-06\demo.py", line 2, in <module>
name[0] = "R"
~~~~^^^
TypeError: 'str' object does not support item assignmentLa primera línea File muestra la ruta completa de tu archivo, así que en tu equipo se verá distinta. El mensaje de verdad está en la última línea: no se puede cambiar un carácter dentro de un texto que ya existe. Entonces, ¿cómo funcionan en realidad las mayúsculas o el recorte? La respuesta: Python no cambia el original; construye un trozo de texto nuevo y te lo devuelve.
name = " rafi "
print(name.strip())
print(name.strip().upper())
print("After all that, name is still:", name)rafi
RAFI
After all that, name is still: rafiname no cambió en absoluto. strip() produjo un trozo de texto limpio nuevo, y nosotros solo lo imprimimos —nunca lo guardamos—.
Así que hay que guardar el resultado:
name = " rafi "
clean_name = name.strip().upper()
print(clean_name)RAFIO asignarlo de vuelta al mismo nombre: name = name.strip(). Este error de llamar a un método y tirar el resultado le pasa a todo el mundo al principio. Y no lanza ningún error, por eso tarda un poco en detectarse.
Métodos útiles
raw = " Rafi Ahmed "
print(raw.strip())
print(raw.strip().lower())
print(raw.strip().upper())
print(raw.strip().replace(" ", "_"))
print(len(raw), len(raw.strip()))
print("rafi" in raw.lower())Rafi Ahmed
rafi ahmed
RAFI AHMED
Rafi_Ahmed
14 10
Truestrip()— quita los espacios en blanco de los extremos (no del medio)lower()/upper()— cambia mayúsculas y minúsculasreplace(a, b)— poneben todas partes donde aparecíaain— dice si un trozo de texto aparece dentro de otro
Y split() parte el texto en trozos:
full_name = "Rafi Ahmed Khan"
parts = full_name.split(" ")
print(parts)
print(parts[0])
print(len(parts))['Rafi', 'Ahmed', 'Khan']
Rafi
3Lo que hay entre corchetes es una lista, que tiene su propio capítulo más adelante en el curso. De momento basta con saber que split() devuelve los trozos así, y que un índice saca un trozo.
Limpia antes de comparar. Si un usuario escribe"Rafi ", eso no es igual a"rafi"—un espacio al final y una mayúscula son dos diferencias entre ellos—. Por eso ejecutar.strip().lower()antes de comparar es casi un hábito universal en los proyectos reales.
f-strings — la forma fácil de construir un mensaje
Mezclar texto y números hasta ahora ha sido engorroso. Una f-string lo pone fácil: una f antes de la comilla, y dentro de las llaves {} lo que quieras:
name = "Rafi"
items = 3
price = 12.5
print(f"Hello, {name}!")
print(f"{items} items cost {items * price}")
print(f"Rounded: {items * price:.2f}")Hello, Rafi!
3 items cost 37.5
Rounded: 37.50Hay tres ventajas: puedes calcular dentro de las llaves (items * price), nunca tienes que pensar en los tipos (los números se convierten en texto solos), y :.2f fija el número de decimales —algo que necesita toda muestra de una cifra monetaria—.
Mira qué pasa cuando se olvida la f:
name = "Rafi"
print("Hello, {name}")Hello, {name}Nada de error, solo un mensaje equivocado. Verlo una vez hace que después sea fácil detectarlo.
Un ejemplo completo
account.py:
# Turn a raw form entry into a clean display name and a login id
raw_input_name = " Rafi Ahmed "
domain = "example.com"
clean = raw_input_name.strip()
parts = clean.split(" ")
first_name = parts[0]
last_name = parts[-1]
login_id = f"{first_name.lower()}.{last_name.lower()}"
email = f"{login_id}@{domain}"
initials = f"{first_name[0]}{last_name[0]}"
print(f"Display name : {clean}")
print(f"Login id : {login_id}")
print(f"Email : {email}")
print(f"Initials : {initials}")
print(f"Name length : {len(clean)} characters")Display name : Rafi Ahmed
Login id : rafi.ahmed
Email : [email protected]
Initials : RA
Name length : 10 characters¿Por qué parts[-1]? Porque el nombre de alguien puede tener tres partes. Tomar el último trozo desde atrás funciona haya dos o tres partes.
Cuando algo falla
IndexError: string index out of range El índice que pediste se pasa del final del texto. Recuerda que si len(word) es 6, los índices válidos van del 0 al 5. Para el último carácter, lo más seguro es escribir word[-1].
TypeError: 'str' object does not support item assignment Intentaste cambiar un carácter dentro del texto. Eso no es posible —construye texto nuevo en su lugar, por ejemplo word = "R" + word[1:]—.
Llamé al método y no cambió nada El resultado no se guardó en ningún sitio. name.strip() no cambia name; hace falta name = name.strip().
strip() no quita los espacios del medio strip() solo funciona en los dos extremos. Para quitar los de dentro usa replace(" ", "").
El mensaje de la f-string sale mal Comprueba que haya una f justo antes de la comilla. Sin ella, las llaves se imprimen como caracteres corrientes.
NameError — el nombre dentro de la f-string es desconocido Lo que escribiste dentro de las llaves nunca se creó, o está mal escrito.
Paso 4 de 6 — Predice
Comprueba lo que has entendido
¿Cuál es la salida de estas cuatro líneas?
word = "PYTHON"
print(word[0])
print(word[-1])
print(word[1:4])- AP N YTH
- BY N YTHO
- CP O YTH
- DP N YTHO
La intención era imprimir Hello, RAFI!, pero el nombre sale en minúsculas y todavía con espacios alrededor. ¿Por qué?
name = " rafi "
name.strip()
name.upper()
print(f"Hello, {name}!")- AA un trozo de texto solo se le puede llamar un método una vez, no dos
- BUna f-string no puede mostrar el resultado de un método
- C`strip()` y `upper()` no cambian el original —devuelven texto nuevo, así que hay que asignar el resultado de vuelta a `name`—
- DNo se puede llamar `strip()` antes de `upper()`; el orden hay que invertirlo
¿Qué imprime esta f-string?
item = "pen"
qty = 3
price = 12.5
print(f"{qty} x {item} = {qty * price:.2f}")- A3 x pen = 37.50
- B3 x pen = 37.5
- C{qty} x {item} = {qty * price}
- D3 x pen = 3 * 12.5
Para responder necesitas una cuenta
Inicia sesión para comprobar tus respuestas
Las preguntas están arriba, y resolverlas mentalmente es lo que de verdad importa. Inicia sesión para ver las respuestas, las explicaciones y las pistas de tres niveles.
Tu turno
Escribe un archivo llamado slug.py que convierta un título en una forma adecuada para una dirección web.
Parte de title = " Learn Python Step By Step ", y la salida debe ser:
Title : Learn Python Step By Step
Slug : learn-python-step-by-step
Slug length: 25Cuatro condiciones:
- Quita los espacios de sobra de los dos extremos
- Pon todo en minúsculas
- Cambia los espacios de dentro por guiones
- Imprime las tres líneas con f-strings
Luego haz una cosa más: cambia title a " Python for Beginners " y ejecútalo. Si el título nuevo sale bien sin que toques el código, significa que escribiste un cálculo de verdad en vez de teclear las respuestas a mano.
Esta misión tiene más
Lo que has leído arriba es la misión completa: no se ha recortado nada. Pro añade:
- Qué ocurre realmente por debajo: cómo ejecuta Python esto
- La solución completa del ejercicio, resuelta paso a paso
- Ejercicios extra más difíciles
- La pregunta de entrevista sobre este tema, con una respuesta modelo
Paso 6 de 6
Reto — el quiz del capítulo
Diez preguntas de fácil a difícil. Las últimas son difíciles a propósito.
Inicia sesión para hacer el quiz