He aquí algunos ejemplos del uso de índices para obtener un sólo elemento de una lista:
>>> lista = ['cero','uno','dos','tres','cuatro','cinco']Todos estos ejemplos debieran resultarle familiares. Si quiere el primer elemento en la lista vea al índice 0. El segundo elemento es índice 1 y así para toda la lista. Sin embargo, ¿qué tal si desea el último elemento de la lista? Un modo pudiera ser usar la función
>>> lista[0]
'cero'
>>> lista[4]
'cuatro'
>>> lista[5]
'cinco'
len
como lista[len(lista)-1]
.
Este modo funciona porque la función len
siempre
devuelve el último índice más uno. El penúltimo
elemento sería lista[len(lista)-2]
. Hay un modo
más fácil. En Python el último índice es
siempre el índice -1. El penúltimo elemento es índice
-2 y así sucesivamente. Vea algunos ejemplos:
>>> lista[len(lista)-1]Por tanto, cualquier elemento de la lista puede ser indexado de dos modos: desde el principio o desde el final.
'cinco'
>>> lista[len(lista)-2]
'cuatro'
>>> lista[-1]
'cinco'
>>> lista[-2]
'cuatro'
>>> list[-6]
'cero'
Otro modo útil de obtener pedazos de listas es usando rebanadas. Veamos otro ejemplo para darle una idea de para qué son útiles:
>>> lista = [0,'Pedro',2,'S.P.A.M.','Media',42,"Juan","Juana"]Las rebanadas sirven para devolver parte de una lista. El operador de rebanado tiene la forma
>>> lista[0]
0
>>> lista[7]
'Juana'
>>> lista[0:8]
[0,'Pedro',2,'S.P.A.M.','Media',42,"Juan","Juana"]
>>> lista[2:4]
[2, 'S.P.A.M.']
>>> lista[4:7]
['Media', 42, 'Juan']
>>> lista[1:5]
['Pedro', 2, 'S.P.A.M.', 'Media']
lista[primer_indice:siguiente_indice]
.
La rebanada va desde el primer_indice
al índice
anterior al siguiente_indice
. Puede usar ambos tipos de indexado:
>>> lista[-4:-2]Otro truco con rebanadas es el índice tácito. Si el primer índice no es especificado, Python supone que quiere desde el principio de la lista. Si el siguiente indice no es especificado, Python supone que quiere todo el resto de la lista. Algunos ejemplos:
['Media', 42]
>>> list[-4]
'Media'
>>> list[-4:6]
['Media', 42]
>>> lista[:2]Vea un programa de ejemplo (copie y pegue la definición del poema, si así lo prefiere):
[0, 'Pedro']
>>> lista[-2:]
['Juan', 'Juana']
>>> lista[:3]
[0, 'Pedro', 2]
>>> lista[:-5]
[0, 'Pedro', 2]
poema = ["<B>","Dona","Blanca","</B>","esta","cubierta","de","pilares","de","<B>",\y la salida es:
"oro","y","plata","</B>","romperemos","un","pilar", "para', "ver", "a", "<B>","Dona",\
"Blanca","</B>"]
def sacar_negritas(lista):
verdadero = 1
falso = 0
## es_negrita dice si estamos viendo a una sección en negrita del texto
es_negrita = falso
## comienza_bloque es el indice del comienzo ya sea de un fragmento
## normal o un fragmento en negrita del texto
comienza_bloque = 0
for indice in range(len(lista)):
##Maneja comienzo de texto negrita
if lista[indice] == "<B>":
if es_negrita:
print "Error: Extra comienzo de negrita"
##print "No negrita:",list[comienzo_bloque:indice]
es_negrita = verdadero
comienzo_bloque = indice+1
##Maneja final de texto negrita
if lista[indice] == "</B>":
if not es_negrita:
print "Error: Extra cierre de negrita"
print "Negrita [",comienzo_bloque,":",indice,"] ",\
lista[comienzo_bloque:indice]
es_negrita = falso
comienzo_bloque = indice+1
sacar_negritas(poema)
Negrita [ 1 : 3 ] ['Dona', 'Blanca']
Negrita [ 10 : 13 ] ['oro', 'y', 'plata']
Negrita [ 21 : 23 ] ['Dona', 'Blanca']
La función sacar_negritas
toma una lista donde cada
elemento es una palabra o un símbolo. Los símbolos que
busca con <B>
el cual comienza texto en negrita y <\B>
el cual termina texto en negrita. La función sacar_negritas
recorre la lista y busca símbolos de comienzo y final.
El siguiente aspecto de las listas es copiarlas. Si trata algo sencillo como:
>>> a = [1,2,3]Esto probablemente resulte desconcertante, ya que una modificación a bresultó en que también a cambiara. Lo que pasó es que la asignación
>>> b = a
>>> print b
[1, 2, 3]
>>> b[1] = 10
>>> print b
[1, 10, 3]
>>> print a
[1, 10, 3]
b = a
hace a b
una referencia a a. Esto significa que podemos considerar
a b como otro nombre para a. Por lo tanto, cualquier
modificación a b también afecta a a.
Sin embargo, algunas asignaciones no crean dos nombres para una lista:
>>> a = [1,2,3]
>>> b = a*2
>>> print a
[1, 2, 3]
>>> print b
[1, 2, 3, 1, 2, 3]
>>> a[1] = 10
>>> print a
[1, 10, 3]
>>> print b
[1, 2, 3, 1, 2, 3]
En este caso b no es una referencia a a porque la expresión
a*2
crea una lista nueva. Luego el enunciadob =
a*2
da a b una referencia a a*2
más que
una referencia a a. Todas las operaciones de asignación
crean una referencia. Cuando usted pasa una lista como argumento de
una función, también crea una referencia. La mayor parte
del tiempo no tiene que preocuparse por crear referencias y no copias. Sin
embargo, cuando necesite modificar una lista sin afectar a otra tiene que
asegurarse que realmente haya creado una copia.
Hay varios modos para hacer una copia de una lista. El más simple, que funciona casi todo el tiempo es el operador rebanador ya que siempre hace una nueva lista aún cuando la rebanada abarca toda la lista:
>>> a = [1,2,3]
>>> b = a[:]
>>> b[1] = 10
>>> print a
[1, 2, 3]
>>> print b
[1, 10, 3]
Tomar la rebanada [:] crea una nueva copia de la lista. Sin embargo, solamente copia la lista más externa. Cualquier sublista contenida será una referencia a la sublista en la lista original. Por tanto, cuando la lista contiene otras listas como elementos, necesitamos copiar también las listas más internas. Puede hacerlo manualmente, pero Python contiene un módulo que lo hace. Use la función deepcopy del módulo copy :
>>> import copyPrimero que nada, note que a es un arreglo de arreglos (o lista de listas). Luego observe que cuando ejecutamos
>>> a = [[1,2,3],[4,5,6]]
>>> b = a[:]
>>> c = copy.deepcopy(a)
>>> b[0][1] = 10
>>> c[1][1] = 12
>>> print a
[[1, 10, 3], [4, 5, 6]]
>>> print b
[[1, 10, 3], [4, 5, 6]]
>>> print c
[[1, 2, 3], [4, 12, 6]]
b[0][1] = 10
tanto a como b cambian, pero c no. Esto
es debido a que las listas más internas son referencias cuando hacemos
rebanadas, pero condeepcopy c fue copiado totalmente.
Entonces, ¿debería preocuparme acerda de referencias cada
vez que uso una función o una asignación? Las
buenas noticias son que sólo tiene que preocuparse de las referencias
cuando usa diccionarios o listas. Los números y las hileras
crean referencias al momento de asignación, pero cada operación
que modifica números e hileras crea una nueva copia de modo que no
puede modificarlos inadvertidamente. Sí debe pensar acerca de
referencias cuando modifique una lista o un diccionario.
En este momento quizá esté preguntándose porqué existen las referencias. La razón básica es velocidad. Es mucho más rápido hacer una referencia a una lista de mil elementos que copiar todos los elementos. La otra razón es que permite que una función modifique la lista o diccionario que recibe como parámetro. Sólo recuerde que las referencias existen si llega a tener algún problema extraño de datos que cambian cuando no debieran.