Cadenas

Escrito el Lunes 15 de Junio del 2009 por Ealdor

Tabla que resume los literales de cadena más comunes y sus operaciones. Las cadenas vacias se escriben como un par de comillas (dobles o simples) con nada en medio, y hay una variedad de maneras de codificar cadenas. Para el procesamiento, las cadenas soportan operaciones de expresiones como la concatenación (combinando cadenas), slicing (extraer secciones), indexación, y demás. A parte de las expresiones, Python tambien provee un conjunto de métodos que implementan las tareas especificas de cadenas más comunes, así como modulos para las tareas mas avanzadas de procesamiento de texto:

Operadores Interpretación
s1 = '' Cadena vacía
s2 = "spam's" Comillas dobles
block = """...""" Bloques comilla-triple
s3 = r'\temp\spam' Cadenas sin tratar (raw)
s4 = u'spam' Cadenas unicode
s1 + s2
s2 * 3
Concatenar, repetir
s2[i]
s2[i:j]
len(s2)
Indexación, slice, longitud
"a %s parrot" % type Formato de cadenas
s2.find('pa')
s2.rstrip()
s2.replace('pa', 'xx')
s1.split(',')
s1.isdigit()
s1.lower()
Llamada a métodos de cadenas: buscar, eliminar espacio en blanco,
reemplazar, dividir en delimitador, prueba de contenido, conversión
de mayúsculas, etc.
for x in s2
'spam' in s2
Iteración

[A] Literales

Lo mas complicado sobre las cadenas es que hay muchas maneras de escribirlas en tu código.

(1) Comillas simples y dobles:

Los literales de cadena pueden escribirse encerrados entre dos simples comillas o entre dos comillas dobles. Por ejemplo, las dos siguientes cadenas son identicas:

>>> 'shrubbery', "shrubbery"
('shrubbery', 'shrubbery')

La razón de incluir ambos es para permitirte incrustar un caracter comilla en una cadena sin necesidad de escaparlo con una barra invertida:

>>> 'knight"s', "knight's"
('knight"s', "knight's")
>>> 'knight\'s', "knight\"s"
("knight's", 'knight"s')

Nótese que poner comas entre estas cadenas crearía una tupla, y no una cadena. Tambien, nótese que en todos estos resultados Python prefiere imprimir cadenas en comillas simples, a menos que tengan incrustadas una.

(2) Secuencias de escape:

Las secuencias de escape nos permiten incrustar códigos de byte en cadenas que no pueden ser escritos facilmente en un teclado. El caracter '\', seguido de uno o más caracteres en el literal cadena, son reemplazados por un caracter en el objeto cadena resultante. Por ejemplo:

>>> s = 'a\nb\tc'
>>> s
'a\nb\tc'
>>> print s
a
b	c

Esta cadena tiene 5 bytes de longitud: contiene un byte ASCII 'a', un byte denueva linea, un byte ASCII 'b', etc. Para estar completamente seguro que cuantos bytes hay en esta cadena, usa la función 'len', el cual devuelve el número actual de bytes en una cadena, a pesar de como se muestre:

>>> len(s)
5

Tabla que lista el código de todas las secuencias de código:

Escape Significado
\newline Ignorado
\\ Barra invertida (mantiene una \)
\' Comilla simple (mantiene ')
\" Comilla doble (mantiene ")
\a Campana
\b Retroceso
\f Formfeed
\n Nueva linea
\r Retorno de carro
\t Tabulación horizontal
\v Tabulación vertical
\N{id} Unicode database ID
\uhhhh Unicode 16-bit hex
\Uhhhh... Unicode 32-bit hex
\xhh Valor dígitos hexadecimal
\ooo Valor dígitos octal
\0 Null
\other No es una secuencia de escape

Finalmente, si Python no reconoce el caracter despues de '\' como un código de escape válido, simplemente mantiene la barra invertida en la cadena resultante:

>>> x = "C:\py\code"
>>> x
'C:\\py\\code'
>>> len(x)
10

(3) Cadenas sin tratar (raw):

Sería erroneo tratar de abrir un archivo con un argumento parecido a este:

myfile = open('C:\new\text.dat', 'w')

pensando que esto abriría un archivo llamado 'text.dat' en el directorio 'C:\new'. El problema aquí es que '\n' es tomado como un caracter de nueva linea, y '\t' es reemplazado por una tabulación. Estas son las cosas para las que las cadenas sin tratar son útiles. Si la letra 'r' (mayúscula o minúscula) aparece justo antes de abrir las comillas de la cadena, esto desactiva las secuencias de escape. El resultado es que Python retiene tus barras invertidas literalmente, exactamente tal y como las escribistes. Por tanto, para arreglar el problema del nombre de archivo, solo recuerda añadir la letra 'r' en Windows. Alternativamente, debido a que dos barras invertidas es una secuencia de escape real para una barra invertida, puedes mantener tus barras invertidas simplemente doblando el número de ellas:

myfile = open(r'C:\new\text.dat', 'w')
myfile = open('C:\\new\\text.dat', 'w')

>>> path = r'C:\new\text.dat'
>>> path
'C:\\new\\text.dat'
>>> print path
C:\new\text.dat
>>> len(path)
15

(4) Comilla triple:

Hasta ahora has visto las comillas simples, comillas dobles, escapes y las cadenas sin tratar en acción. Python tambien dispone de un formato de literal de cadena comilla-triple, conocido como bloque de cadena. Esta forma comienza con tres comillas (simples o dobles), seguido de un número de lineas de texto, y cerrado con la misma secuencia de comilla-triple que lo abrió:

>>> mantra = """Always look
... on the bright
...side of life."""
>>>
>>> mantra
'Always look\n on the bright\nside of life.'

Cadenas comilla-triple son útiles cuando necesites texto multilínea en tu programa; por ejemplo, para incrustar mensajes de error multilínea o código HTML o XML en tus archivos de código.

[B] Cadenas en acción

(1) Operaciones básicas:

Las cadenas pueden ser concatenadas usando el operador '+' y repetidas usando el operador '*':

>>> %python
>>> len('abc')
3
>>> 'abc' + 'def'
'abcdef'
>>> 'Ni!' * 4
'Ni!Ni!Ni!Ni!'

Ten cuidado, Python no te permite mezclar números y cadenas en expresiones '+': 'abc'+9 lanza un error en vez de convertir automaticamente '9' a una cadena.

Tambien puedes iterar sobre cadenas en bucles 'for' y testear los miembros con el operador 'in', que es esencialmente una busqueda:

>>> myjob = "hacker"
>>> for c in myjob: print c,
...
h a c k e r
>>> "k" in myjob
True
>>> "z" in myjob
False

(2) Indexación y slicing:

En Python el offset comienza en 0, y termina en un menos que la longitud de la cadena. Python tambien permite extraer elementos de la cadena usando el offset negativo:

>>> S = 'spam'
>>> S[0], S[-2]
('s', 'a')
>>> S[1:3], S[1:], S[:-1]
('pa', 'pam', 'spa')

La primera linea define una cadena de cuatro caracteres, y lo asigna al nombre 'S'. La siguiente linea indexa la cadena de dos maneras: S[0] obtiene el elemento del offset 0 desde la izquierda, y S[-2] obtiene el elemento del offset 2 desde el final (o equivalentemente, en el offset 4+-2 desde el principio).

Imagen

Resumen:

- Indexación (S[i]) obtiene componentes:

- El primer elemento es en offset 0.
- Indexaciones negativas significa contar hacia atras desde el final o la derecha.
- S[0] obtiene el primer elemento. - S[-2] obtiene el segundo elemento desde el final (como S[len(S)-2]).

- Slicing (S[i:j]) extrae secciones contiguas de un secuencia:

- S[1:3] extrae elementos desde el offset 1 hasta el 3 (sin incluirlo).
- S[1:] extrae elementos desde el offset 1 hasta el final.
- S[:3] extrae elementos desde el offset 0 hasta el 3 (sin incluirlo).
- S[:-1] extrae elementos desde el offset 0 hasta el último elemento (sin incluirlo).
- S[:] extrae elementos desde el offset 0 hasta el final.

Extensión del slicing - el tercer limite. El tercer valor es conocido como 'step':

>>> S = 'abcdefghijklmnop'
>>> S[1:10:2]
'bdfhj'
>>> S[::2]
'acegikmo'

>>> S = 'hello'
>>> S[::-1]
'olleh'

>>> S = 'abcedfg'
>>> S[5:1:-1]
'fdec'

[C] Herramientas de conversión de cadena

No se puede sumar un número y una cadena juntas en Python, incluso si la cadena luce como un número. Esto es debido a que '+' puede significar tanto adición como concatenación. ¿Qué hacer entonces?. La función 'int' convierte una cadena en un número, y la función 'str' convierte un número en su representación de cadena. La función 'repr' (y su antiguo equivalente, las comillas hacia atras) tambien convierten un objeto en su representación cadena, pero estos devuelven el objeto como una cadena de código con el cual se puede volver a recrear el objeto:

>>> int("42"), str(42)
(42, '42')
>>> repr(42), `42`
('42', '42')

>>> S = "42"
>>> I = 1
>>> S + I
TypeError: cannot concatenate 'str' and 'int' objects
>>> int(S) + I
43
>>> S + str(I)
'421'

>>> str(3.1415), float("1.5")
('3.1415', 1.5)
>>> text = "1.234E-10"
>>> float(text)
1.2340000000000001e-010

Es posible convertir un caracter solo a su código entero ASCII pasandolo por la función 'ord'. La función 'chr' realiza la operación inversa, cojiendo un código entero ASCII y convirtiendolo a su correspondiente caracter:

>>> ord('s')
115
>>> chr(115)
's'

>>> S = '5'
>>> S = chr(ord(S) + 1)
>>> S
'6'
>>> S = chr(ord(S) + 1)
>>> S
'7'

Al menos para una cadena de un solo caracter, esto provee una alternativa a usar la funcion 'int' para convertir desde cadena a entero:

>>> int('5')
5
>>> ord('5') - ord('0')
5
>>> B = '1101' >>> I = 0 >>> while B: ... I = I * 2 + (ord(B[0]) - ord('0')) ... B = B[1:] ... >>> I 13

[D] Cambiando una cadena

Las cadenas son inmutables, ya que no pueden ser cambiadas en el lugar. Así que para modificar una cadena, necesitas crear y asignar una nueva cadena usando herramientas como concatenación y slicing, y luego, si deseas, asignarle el resultado de vuelta al nombre de la cadena original. Tambien puedes obtener resultados similares con el método de cadena llamado 'replace':

>>> S = 'spam'
>>> S[0] = "x"
Raises an error!

>>> S = S + 'SPAM!'
>>> S
'spamSPAM!'
>>> S = S[:4] + 'Burger' + S[-1]
>>> S
'spamBurger!'

>>> S = 'splot'
>>> S = S.replace('pl', 'pamal')
>>> S
'spamalot'

[E] Formato de cadenas

Cuando aplicamos el operador '%' a las cadenas, este realiza el mismo papel que la función 'sprintf' en C:

>>> exclamation = "Ni"!
>>> "The knights who say %s!" % exclamation
'The knights who say Ni!'

>>> "%d %s %d you" % (1, 'spam', 4)
'1 spam 4 you'

>>> "%s -- %s -- %s" % (42, 3.14159, [1, 2, 3])
'42 -- 3.14159 -- [1, 2, 3]'

Nótese que cuando insertas mas de un valor, necesitas agrupar los valores de la derecha entre paréntesis. En el tercer ejemplo se insertan tres valores (un entero, un objeto real y un objeto lista), pero todos los objetivos de la derecha son '%s', que es la conversión a cadena. Debido a que todos los tipos de objetos pueden ser convertidos a una cadena, todos los tipos de objetos funcionan con el código de conversión '%s'.

Tabla con los códigos de formato de cadena:

Código Significado
%s Cadena (o cualquier objeto)
%r s, pero usa repr, no str
%c Caracter
%d Decimal (entero)
%i Entero
%u Sin signo (entero)
%o Entero octal
%x Entero hexadecimal
%X x, pero imprime en mayúsculas
%e Exponente número real
%E e, pero imprime en mayúsculas
%f Real decimal
%g Real e o f
%G Real E o f
%% Literal %

Entre el '%' y el caracter, puedes hacer las siguientes cosas: proveer un clave de diccionario; flags de listas que especifican cosas somo justificación a la izquierda (-), signo numérico (+), y relleno de ceros (0); dar una longitud y el número de dígitos despues del punto decimal; y más:

>>> x = 1234
>>> res = "integers: ...%d...%-6d...%06d" % (x, x, x)
>>> res
'integers: ...1234...1234  ...001234'

>>> x = 1.23456789
>>> x
1.2345678899999999
>>> '%e | %f | %g' % (x, x, x)
'1.234568e+000 | 1.234568 | 1.23457'
>>> '%-6.2f | %05.2f | %+06.1f' % (x, x, x)
'1.23   | 01.23 | +001.2'
>>> "%s" % x, str(x)
('1.23456789', '1.23456789')

El formateo de cadenas tambien permite la conversión de objetivos en la izquierda para referirse a claves en un diccionario a la derecha:

>>> "%(n)d %(x)s" % {"n":1, "x":"spam"}
'1 spam'

>>> reply = """
Greetings...
Hello %(name)s!
Your age squared is %(age)s
"""
>>> values = {'name': 'Bob', 'age': 40}
>>> print reply % values
Greetings...
Hello Bob!
Your age squared is 40

[F] Métodos de cadena

La siguiente tabla resume los métodos de cadena (asegurate de comprobar el manual de la librería estandar de Python para la lista más actualizada, o ejecuta la llamada 'help' en cualquier cadena).

S.capitalize() S.ljust(width)
S.center(width) S.lower()
S.count(sub [, start [, end]]) S.lstrip()
S.encode([encoding [,errors]]) S.replace(old, new [, maxsplit])
S.endswith(suffix [, start [, end]]) S.rfind(sub [,start [,end]])
S.expandtabs([tabsize]) S.rindex(sub [, start [, end]])
S.find(sub [, start [, end]]) S.rjust(width)
S.index(sub [, start [, end]]) S.rstrip()
S.isalnum() S.split([sep [,maxsplit]])
S.isalpha() S.splitlines([keepends])
S.isdigit() S.startswith(prefix [, start [, end]])
S.islower() S.strip()
S.isspace() S.swapcase()
S.istitle() S.title()
S.isupper() S.translate(table [, delchars])
S.join(seq) S.upper()

Algunos ejemplos:

>>> S = 'spammy'
>>> S = S.replace('mm', 'xx')
>>> S
'spaxxy'

>>> 'aa$bb$cc$dd'.replace('$', 'SPAM')
'aaSPAMbbSPAMccSPAMdd'

>>> S = 'xxxxSPAMxxxxSPAMxxxx'
>>> where = S.find('SPAM')
>>> where
4
>>> S = S[:where] + 'EGGS' + S[(where+4):]
>>> S
'xxxxEGGSxxxxSPAMxxxx'

>>> S = 'xxxxSPAMxxxxSPAMxxxx'
>>> S.replace('SPAM', 'EGGS')
'xxxxEGGSxxxxEGGSxxxx'
>>> S.replace('SPAM', 'EGGS', 1)
'xxxxEGGSxxxxSPAMxxxx'

>>> line = 'aaa bbb ccc'
>>> cols = line.split()
>>> cols
['aaa', 'bbb', 'ccc']

>>> line = "The knights who say Ni!\n"
>>> line.rstrip()
'The knights who say Ni!'
>>> line.upper()
'THE KNIGHTS WHO SAY NI!\n'
>>> line.isalpha()
False
>>> line.endswith('Ni!\n')
True