Cadenas de texto¶

Imagen generada con Inteligencia Artificial
Las cadenas de texto son secuencias de caracteres. También se les conoce como "strings" y nos permiten almacenar información textual de manera muy cómoda.
Es importante señalar que desde Python 3.0 las cadenas de texto se almacenan en el estándar Unicode, lo que supone una gran ventaja con respecto a versiones antiguas del lenguaje (que usaban bytes para esto). Además permite representar una cantidad ingente de símbolos incluyendo los famosos emojis 😎.
Creando "strings"¶
Para escribir una cadena de texto en Python basta con rodear los caracteres con comillas simples:
Para incluir comillas dobles dentro de la cadena de texto no hay mayor inconveniente:
>>> 'Los llamados "strings" son secuencias de caracteres'
'Los llamados "strings" son secuencias de caracteres'
Para incluir comillas simples dentro de la cadena de texto cambiamos las comillas exteriores a comillas dobles(1):
- Otra opción es escapar las comillas simples:
'Los llamados \'strings\' son secuencias de caracteres'.
>>> "Los llamados 'strings' son secuencias de caracteres"
"Los llamados 'strings' son secuencias de caracteres"
Cuestión de estilo
Efectivamente, como se puede ver, las cadenas de texto en Python se pueden escribir con comillas simples o con comillas dobles. Es indiferente. En mi caso personal prefiero usar comillas simples .
Hagas lo que hagas... ¡haz siempre lo mismo!
Comillas triples¶
Una forma alternativa de crear cadenas de texto es utilizar comillas triples. Su aplicación está pensada principalmente para cadenas multilínea:
>>> poem = """To be, or not to be, that is the question:
... Whether 'tis nobler in the mind to suffer
... The slings and arrows of outrageous fortune,
... Or to take arms against a sea of troubles"""
En este caso sí que se debería utilizar comillas dobles (triples) siguiendo las indicaciones de la guía de estilo de Python:
PEP 257
In Python, single-quoted strings and double-quoted strings are the same. This PEP does not make a recommendation for this. Pick a rule and stick to it. When a string contains single or double quote characters, however, use the other one to avoid backslashes in the string. It improves readability.
For triple-quoted strings, always use double quote characters to be consistent with the docstring convention in PEP 257.
Cadena vacía¶
La cadena vacía es aquella que no contiene ningún carácter. Aunque a priori no lo pueda parecer, es un recurso importante en cualquier programa (y lenguaje de programación). Su representación en Python es la siguiente:
Conversión¶
Podemos crear "strings" a partir de otros tipos de datos mediante la función str():
Para el caso contrario de convertir un "string" a un valor numérico, tenemos a disposición las funciones ya vistas:
En aquellos casos donde la cadena de texto no se pueda convertir, Python nos indicará que hay un error:
>>> float('3.1a')
Traceback (most recent call last):
Cell In[1], line 1
float('3.1a')
ValueError: could not convert string to float: '3.1a'
Otras bases
Hay que tener en cuenta un detalle. La función int() también admite la base en la que se encuentra el número. Eso significa que podemos pasar un número, por ejemplo, en hexadecimal (como "string") y lo podríamos convertir a su valor entero:
Secuencias de escape¶
Python permite escapar el significado de algunos caracteres para conseguir otros resultados. Si escribimos una barra invertida \ antes del carácter en cuestión, le otorgamos un significado especial.
Quizás la secuencia de escape más conocida es \n que representa un salto de línea, pero existen muchas otras:
Los ejemplos anteriores se han mostrado con el intérprete de Python. Aún así hemos utilizado la función print() porque nos permite ver realmente el resultado de utilizar los caracteres escapados.
Cadenas en crudo¶
Hay situaciones en las que nos interesa que los caracteres especiales pierdan ese significado y poder usarlos de otra manera. Existe un modificador de cadena que proporciona Python para tratar el texto en bruto. Es el llamado "raw data" y se aplica anteponiendo una r a la cadena de texto.
Veamos algunos ejemplos:
Expresiones regulares
El modificador r'' es muy utilizado para escribir expresiones regulares.
Más sobre print()¶
Hemos estado utilizando la función print() de manera sencilla, pero admite algunos parámetros interesantes.
Veamos algunos ejemplos:
>>> msg1 = '¿Sabes por qué estoy acá?'
>>> msg2 = 'Porque me apasiona'
>>> print(msg1, msg2)#(1)!
¿Sabes por qué estoy acá? Porque me apasiona
>>> print(msg1, msg2, sep='|')#(2)!
¿Sabes por qué estoy acá?|Porque me apasiona
>>> print(msg2, end='!!')#(3)!
Porque me apasiona!!
- Podemos imprimir todas las variables que queramos separándolas por comas.
- El separador por defecto entre las variables es un espacio. Podemos cambiar el carácter que se utiliza como separador entre cadenas a través de
sep. - El carácter de final de texto es un salto de línea. Podemos cambiar el carácter que se utiliza como final de texto a través de
end.
Leer datos desde teclado¶
Los programas se desarrollan (habitualmente) para tener una cierta interacción con el usuario. Una de las formas de interacción es solicitar la entrada de datos por teclado. Como muchos otros lenguajes de programación, Python también nos ofrece la posibilidad de leer la información introducida por teclado. Para ello se utiliza la función input().
Veamos algunos ejemplos:
>>> name = input('Introduzca su nombre: ')
Introduzca su nombre: Sergio
>>> name
'Sergio'
>>> type(name)
str
>>> age = input('Introduzca su edad: ')#(1)!
Introduzca su edad: 41
>>> age
'41'
>>> type(age)
str
- La función
input()siempre nos devuelve un objeto de tipo cadena de texto ostr. Tenerlo muy en cuenta a la hora de trabajar con números, ya que debemos realizar una conversión explícita.
Advertencia
Aunque está permitido, NUNCA llames input a una variable porque destruirías la función que nos permite leer datos desde teclado. Y tampoco uses nombres derivados como _input o input_ ya que no son nombres representativos que identifiquen el propósito de la variable.
Ejercicio
Escribe una calculadora básica: solicita al usuario dos números y una operación (+, -, *, /) y muestra el resultado formateado como cadena de texto.
Operaciones con "strings"¶
Combinar cadenas¶
Podemos combinar dos o más cadenas de texto utilizando el operador +:
>>> proverb1 = 'Cuando el río suena'
>>> proverb2 = 'agua lleva'
>>> proverb1 + proverb2
'Cuando el río suenaagua lleva'
>>> proverb1 + ', ' + proverb2#(1)!
'Cuando el río suena, agua lleva'
- Podemos "sumar" todas la cadenas de texto que sean necesarias.
Repetir cadenas¶
Podemos repetir dos o más cadenas de texto utilizando el operador *:
Obtener un caracter¶
Los "strings" están indexados y cada carácter tiene su propia posición (numérica).
Veamos el ejemplo de la cadena de texto 'Hola, Mundo':
Para acceder a cada caracter podemos hacer uso de su índice que, en Python, puede ser tanto positivo como negativo:
En caso de que intentemos acceder a un índice que no existe, obtendremos un error por fuera de rango:
>>> sentence[50]
Traceback (most recent call last):
Cell In[1], line 1
sentence[50]
IndexError: string index out of range
Las cadenas de texto son tipos de datos inmutables. Es por ello que no podemos modificar un carácter directamente.
Veamos un ejemplo:
>>> song = 'Hey Jude'
>>> song[4] = 'D'
Traceback (most recent call last):
Cell In[2], line 1
song[4] = 'D'
TypeError: 'str' object does not support item assignment
Existen formas de modificar una cadena de texto que veremos más adelante, aunque realmente no estemos transformando el original sino creando un nuevo objeto con las modificaciones.
Sobre las constantes
No hay que confundir las constantes con los tipos de datos inmutables. Es por ello que las variables que almacenan cadenas de texto, a pesar de ser inmutables, no se escriben en mayúsculas.
Trocear una cadena¶
Es posible extraer "trozos" ("rebanadas")1 de una cadena de texto. Tenemos varias aproximaciones para ello:
Se indica con la sintaxis [start:end]
Se llega hasta end - 1
El paso indica cuánto nos movemos en el troceado (tamaño del salto). El paso por defecto es 1, pero este valor se puede modificar. Se indica con la sintaxis [start:end:step]
- paso =
2
Se llega hasta end - 1
Si no especificamos hasta dónde llegar, el troceado se extenderá hasta el final de la cadena de texto. Se indica con la sintaxis [start:]
Si no especificamos desde dónde empezar, el troceado empezará por el principio de la cadena de texto. Se indica con la sintaxis [:end]
Se llega hasta end - 1
Longitud de la cadena¶
Para obtener la longitud de una cadena podemos hacer uso de len(), una función común a prácticamente todos los tipos y estructuras de datos en Python.
Veamos algunos ejemplos:
>>> proverb = 'Lo cortés no quita lo valiente'
>>> len(proverb)
30
>>> empty = ''
>>> len(empty)#(1)!
0
- La cadena vacía siempre tiene longitud 0.
Ejercicio
Dada una cadena de texto, muestra su primera mitad y su segunda mitad por separado. Si la longitud es impar, la primera mitad tendrá un carácter menos.
Pertenencia de un elemento¶
Si queremos comprobar que una determinada subcadena se encuentra en una cadena de texto utilizamos el operador in para ello. Se trata de una expresión que tiene como resultado un valor "booleano" verdadero o falso.
Veamos algunos ejemplos:
>>> proverb = 'Más vale malo conocido que bueno por conocer'
>>> 'malo' in proverb
True
>>> 'mal' in proverb#(1)!
True
>>> 'bueno' in proverb
True
>>> 'regular' in proverb
False
>>> '' in proverb#(2)!
True
- El operador
inno busca "palabras", únicamente secuencias de caracteres. - La cadena vacía está en todas las cadenas.
Habría que prestar atención al caso en el que intentamos descubrir si una subcadena no está en la cadena de texto:
>>> dna_sequence = 'ATGAAATTGAAATGGGA'
>>> not('C' in dna_sequence)#(1)!
True
>>> 'C' not in dna_sequence#(2)!
True
- Esta podría ser una primera aproximación.
- Esta es la forma realmente pitónica.
Limpiar cadenas¶
Cuando leemos datos del usuario o de cualquier fuente externa de información, es bastante probable que se incluyan en esas cadenas de texto caracteres de relleno2 al comienzo y al final. Python nos ofrece la posibilidad de eliminar estos caracteres u otros que no nos interesen.
La función strip() se utiliza para eliminar caracteres del principio y del final de un "string". También existen variantes de esta función para aplicarla únicamente al comienzo o únicamente al final de la cadena de texto.
Supongamos que debemos procesar un fichero con números de serie de un determinado artículo. Cada línea contiene el valor que nos interesa pero se han "colado" ciertos caracteres de relleno que debemos limpiar:
>>> serial_number = '\n\t \n 48374983274832 \n\n\t \t \n'
>>> serial_number.strip()
'48374983274832'
Valores por defecto
Si no se especifican los caracteres a eliminar, strip() usará por defecto cualquier combinación de espacios en blanco, saltos de línea \n y tabuladores \t.
Hay dos variantes de esta función para especificar "por dónde" hacer la limpieza:
También existe la posibilidad de especificar los caracteres que queremos borrar:
Cadena modificada
La función strip() no modifica la cadena que estamos usando (algo obvio porque los "strings" son inmutables) sino que devuelve una nueva cadena de texto con las modificaciones pertinentes.
Realizar búsquedas¶
Aunque hemos visto que la forma pitónica de saber si una subcadena se encuentra dentro de otra es a través del operador in, Python nos ofrece distintas alternativas para realizar búsquedas dentro de una cadena de texto.
Vamos a partir de una variable que contiene un trozo de la canción Mediterráneo de Joan Manuel Serrat para ejemplificar las distintas opciones que tenemos:
>>> lyrics = """Quizás porque mi niñez
... Sigue jugando en tu playa
... Y escondido tras las cañas
... Duerme mi primer amor
... Llevo tu luz y tu olor
... Por dondequiera que vaya"""
Comprobar si una cadena de texto empieza o termina por alguna subcadena:
Encontrar la primera ocurrencia de alguna subcadena:
Tanto find() como index() devuelven el índice de la primera ocurrencia de la subcadena que estemos buscando, pero se diferencian en su comportamiento cuando la subcadena buscada no existe:
>>> lyrics.find('universo')
-1
>>> lyrics.index('universo')
Traceback (most recent call last):
Cell In[2], line 1
lyrics.index('universo')
ValueError: substring not found
Es posible indicar un rango sobre el que buscar. Para ello podemos indicar los índices de comienzo y/o fin sobre las funciones ya vistas.
Por ejemplo utilizamos find() para buscar la palabra "tu" en la letra de la canción anterior:
>>> lyrics = """Quizás porque mi niñez
... Sigue jugando en tu playa
... Y escondido tras las cañas
... Duerme mi primer amor
... Llevo tu luz y tu olor
... Por dondequiera que vaya"""
>>> lyrics.find('tu')#(1)!
40
>>> lyrics.find('tu', 41)#(2)!
104
>>> lyrics.find('tu', 105, 200)#(3)!
113
- El primer "tu" está en la posición 40.
- Buscamos a partir de la posición 41 y encuentra el segundo "tu" en la posición 104.
- Buscamos entre la posición 105 y la posición 200 y encuentra el tercer "tu" en la posición 113.
Por la derecha
Django proporciona las funciones rfind() y rindex() que se comportan de manera análoga a las ya explicadas pero empiezan la búsqueda por la derecha de la cadena de texto.
Contar ocurrencias¶
Para contabilizar el número de veces que aparece una subcadena utilizamos la función count():
Ejercicio
Dada una frase y dos palabras, determina cuál de las dos palabras aparece más veces en la frase. Muestra la palabra ganadora y su número de ocurrencias.
Reemplazar texto¶
Podemos usar la función replace() indicando la subcadena a reemplazar, la subcadena de reemplazo y cuántas instancias se deben reemplazar. Si no se especifica este último argumento, la sustitución se hará en todas las instancias encontradas.
Veamos un ejemplo:
>>> proverb = 'Quien mal anda mal acaba'
>>> proverb.replace('mal', 'bien')
'Quien bien anda bien acaba'
>>> proverb.replace('mal', 'bien', 1)#(1)!
'Quien bien anda mal acaba'
- Es posible indicar cuántos reemplazos llevar a cabo.
Mayúsculas y minúsculas¶
Python nos permite realizar variaciones en los caracteres de una cadena de texto para pasarlos a mayúsculas y/o minúsculas.
Veamos las distintas opciones disponibles a través del siguiente ejemplo:
>>> proverb = 'quien a buen árbol se arrima Buena Sombra le cobija'
>>> proverb
'quien a buen árbol se arrima Buena Sombra le cobija'
>>> proverb.capitalize()
'Quien a buen árbol se arrima buena sombra le cobija'
>>> proverb.title()
'Quien A Buen Árbol Se Arrima Buena Sombra Le Cobija'
>>> proverb.upper()
'QUIEN A BUEN ÁRBOL SE ARRIMA BUENA SOMBRA LE COBIJA'
>>> proverb.lower()
'quien a buen árbol se arrima buena sombra le cobija'
>>> proverb.swapcase()
'QUIEN A BUEN ÁRBOL SE ARRIMA bUENA sOMBRA LE COBIJA'
Identificando caracteres¶
Hay veces que recibimos información textual de distintas fuentes de las que necesitamos identificar qué tipo de caracteres contienen. Para ello Python nos ofrece un grupo de funciones:
Detectar si todos los caracteres son letras o números:
Detectar si todos los caracteres son alfabéticos:
Detectar si todos los caracteres son números:
Interpolación de cadenas¶
En este apartado veremos cómo interpolar valores dentro de cadenas de texto utilizando diferentes formatos. Interpolar (en este contexto) significa sustituir una variable por su valor dentro de una cadena de texto.
Veamos los estilos que proporciona Python para este cometido:
| Nombre | Símbolo | Soportado |
|---|---|---|
| Estilo "antiguo" | % |
Python 2.0 |
| Estilo "nuevo" | .format() |
Python 2.6 |
| "f-strings" | f'' |
Python 3.6 |
Aunque aún podemos encontrar código Python con el estilo antiguo y el estilo nuevo en el formateo de cadenas, vamos a centrarnos en el análisis de los "f-strings" que se están muy extendidos en el desarrollo actual.
"f-strings"¶
Los f-strings aparecieron en Python 3.6 y se suelen usar en código de nueva creación. Es la forma más potente –y en muchas ocasiones más eficiente– de formar cadenas de texto incluyendo valores de otras variables.
La interpolación en cadenas de texto es un concepto que existe en la gran mayoría de lenguajes de programación y hace referencia al hecho de sustituir los nombres de variables por sus valores cuando se construye un "string".
Para indicar en Python que una cadena es un "f-string" basta con precederla de una f e incluir las variables o expresiones a interpolar entre llaves {...}.
Supongamos que disponemos de los datos de una persona y queremos formar una frase de bienvenida con ellos:
>>> name = 'Leia Organa'
>>> age = 22
>>> role = 'líder de la Alianza Rebelde'
>>> f'Me llamo {name}, tengo {age} años y soy {role}'#(1)!
'Me llamo Leia Organa, tengo 22 años y soy líder de la Alianza Rebelde'
-
Si olvidamos poner la
fdelante de la cadena de texto, no obtendremos ningún eror, únicamente no habrá sustitución (interpolación) de variables:
Podría surgir la duda de cómo incluir llaves dentro de un "f-string", teniendo en cuenta que las llaves son símbolos especiales para la interpolación de variables. La respuesta es duplicar las llaves:
Formateando cadenas¶
Los "f-strings" proporcionan una gran variedad de opciones de formateado: ancho del texto, número de decimales, tamaño de la cifra, alineación, etc. Muchas de estas facilidades se pueden consultar en el artículo Best of Python3.6 f-strings3.
El modificador para formatear enteros es d (entero decimal):
zfill
Django proporciona la función zfill() que rellena la cadena de texto (como número) con la cantidad indicada de ceros:
El modificador para formatear flotantes es f (flotante):
>>> PI = 3.14159265
>>> f'{PI:f}'#(1)!
'3.141593'
>>> f'{PI:.3f}'
'3.142'
>>> f'{PI:12f}'
' 3.141593'
>>> f'{PI:7.2f}'
' 3.14'
>>> f'{PI:07.2f}'
'0003.14'
>>> f'{PI:.010f}'
'3.1415926500'
>>> f'{PI:e}'
'3.141593e+00'
- Por defecto se muestran 6 cifras decimales.
zfill
Django proporciona la función zfill() que rellena la cadena de texto (como número) con la cantidad indicada de ceros:
El modificador para formatear cadenas de texto es s (string):
El modificador para binario es b, para octal es o y para hexadecimal es x:
>>> value = 65_321
>>> f'{value:b}'
'1111111100101001'
>>> f'{value:o}'
'177451'
>>> f'{value:x}'
'ff29'
Por supuesto en el caso de otras bases también es posible aplicar los mismos modificadores de ancho y de relleno vistos para números enteros decimales. Por ejemplo:
Como curiosidad, si utilizamos el modificador X en mayúsculas es como si aplicáramos (automáticamente) un upper() al resultado del valor hexadecimal:
Cambio de base
Nótese la diferencia de obtener el cambio de base con este método frente a las funciones de cambio de base ya vistas previamente que añaden el prefijo de cada base 0b, 0o y 0x.
Modo "debug"¶
A partir de Python 3.8, los "f-strings" permiten imprimir el nombre de la variable y su valor, como un atajo para depurar nuestro código. Para ello sólo tendremos que incluir el símbolo igual = después del nombre de la variable.
Veamos algunos ejemplos:
>>> serie = 'The Simpsons'
>>> imdb_rating = 8.7
>>> num_seasons = 30
>>> f'{serie=}'
"serie='The Simpsons'"
>>> f'{imdb_rating=}'
'imdb_rating=8.7'
>>> f'{serie[4:]=}'#(1)!
"serie[4:]='Simpsons'"
>>> f'{imdb_rating / num_seasons=}'
'imdb_rating / num_seasons=0.29'
- También podemos añadir... ¡expresiones!
Modo "representación"¶
Si imprimimos el valor de una variable utilizando un "f-string", obviamente veremos ese valor tal y como esperaríamos:
>>> name = 'Steven Spielberg'
>>> print(f'{name}') # NO HAGAS ESTO! Usa: print(name)
Steven Spielberg
Pero si quisiéramos ver la representación del objeto, tal y como se almacena internamente, podríamos utilizar el modificador !r en el "f-string":
Ejercicio
Solicita al usuario su nombre, apellido, edad y altura. Muestra un resumen usando f-strings con el nombre en mayúsculas, la edad alineada a la derecha en un campo de 5 caracteres y la altura con 2 decimales.
Caracteres Unicode¶
Los programas de computador deben manejar una amplia variedad de caracteres. Simplemente por el hecho de la internacionalización hay que mostrar mensajes en distintos idiomas (inglés, francés, japonés, español, etc.). También es posible incluir "emojis" u otros símbolos.
Python utiliza el estándar Unicode para representar caracteres. Eso significa que tenemos acceso a una amplia carta de caracteres que nos ofrece este estándar de codificación.
Unicode asigna a cada carácter (al menos) dos atributos:
- Un código numérico único (habitualmente se muestra en hexadecimal).
- Un nombre representativo.
Veamos un ejemplo con el típico "emoji" de un cohete (definido en este cuadro Unicode).
Python nos permite convertir de...
Mediante la función ord():
- Es habitual trabajar los códigos Unicode en formato hexadecimal.
Ejercicio
Dado un carácter, muestra su nombre Unicode, su código de punto de código (ord()) y su representación hexadecimal.
ASCII¶
En los albores de la computación los caracteres se representaban utilizando el código ASCII. En un primer momento solo incluía letras mayúsculas y números, pero en 1967 se agregaron las letras minúsculas y algunos caracteres de control, formando así lo que se conoce como US-ASCII, es decir los caracteres del 0 al 127.
Podemos obtener algunos de los caracteres imprimibles del código ASCII mediante Python:
Comparar cadenas¶
Cuando comparamos dos cadenas de texto lo hacemos en términos lexicográficos. Es decir, se van comparando los caracteres de ambas cadenas uno a uno y se va chequeando cuál está "antes".
Podemos afirmar (al menos en Python) que la cadena de texto 'arca' es menor que la cadena de texto 'arpa':
-
Python analiza cada carácter:
ord('a') #97ord('a') #97
ord('r') #114ord('r') #114
ord('c') #99ord('p') #112El último carácter no se analiza ya que en este punto sabemos positivamente que la primera cadena de texto es menor que la segunda.
Otros ejemplos:
>>> 'a' < 'antes'
True
>>> 'antes' < 'después'
True
>>> 'después' < 'ahora'
False
>>> 'ahora' < 'a'
False
Ten en cuenta que en Python Unicode la letras mayúsculas van antes que las minúsculas:
- Cuestión de códigos...
Ejercicios¶
- Dado un color en formato hexadecimal (ej.
#FF8800), muéstralo formateado comoR: 255, G: 136, B: 0. - Dado un nombre completo en formato
"Nombre Apellido", muéstralo invertido como"Apellido, Nombre". - Dada una cadena con palabras separadas por comas, sepáralas y muéstralas numeradas, una por línea.
- Dado el número de un NIF español (8 dígitos), calcula y muestra su letra de control usando la tabla de letras
TRWAGMYFPDXBNJZSQVHLCKE. - Dada una cadena y un número
n, muestra la cadena repetidanveces sin espacios entre las repeticiones. - Dadas dos cadenas, calcula cuántos caracteres tienen en común (sin repetir) y muestra el resultado.
- Dada una línea de texto con un encabezado Markdown (ej.
## Título), conviértela a su equivalente en HTML (ej.<h2>Título</h2>). - Dada una cadena de texto, cuenta cuántas veces aparece la palabra
"sheep"(o su equivalente en español). - Dada una cadena con espacios al inicio y al final, elimina solo el primer y el último espacio (sin usar
strip()). - Dada una expresión matemática como cadena (ej.
"integral(x^2)"), extrae y muestra únicamente la parte entera del argumento. - Dado un nombre y un número, genera la frase
"Hello, {nombre}!"repetida tantas veces como indique el número. - Dado un número entero como cadena, muestra su primer y último dígito.